alepha 0.13.8 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/api/audits/index.d.ts +2 -1
  2. package/dist/api/audits/index.d.ts.map +1 -0
  3. package/dist/api/files/index.d.ts +2 -1
  4. package/dist/api/files/index.d.ts.map +1 -0
  5. package/dist/api/jobs/index.d.ts +158 -157
  6. package/dist/api/jobs/index.d.ts.map +1 -0
  7. package/dist/api/notifications/index.d.ts.map +1 -0
  8. package/dist/api/parameters/index.d.ts +4 -4
  9. package/dist/api/parameters/index.d.ts.map +1 -0
  10. package/dist/api/users/index.d.ts +132 -131
  11. package/dist/api/users/index.d.ts.map +1 -0
  12. package/dist/api/verifications/index.d.ts.map +1 -0
  13. package/dist/batch/index.d.ts.map +1 -0
  14. package/dist/bucket/index.d.ts.map +1 -0
  15. package/dist/cache/core/index.d.ts.map +1 -0
  16. package/dist/cache/redis/index.d.ts.map +1 -0
  17. package/dist/cli/index.d.ts +44 -32
  18. package/dist/cli/index.d.ts.map +1 -0
  19. package/dist/cli/index.js +380 -109
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/command/index.d.ts +11 -1
  22. package/dist/command/index.d.ts.map +1 -0
  23. package/dist/command/index.js +45 -6
  24. package/dist/command/index.js.map +1 -1
  25. package/dist/core/index.browser.js +1334 -1318
  26. package/dist/core/index.browser.js.map +1 -1
  27. package/dist/core/index.d.ts +75 -71
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +1337 -1321
  30. package/dist/core/index.js.map +1 -1
  31. package/dist/core/index.native.js +1337 -1321
  32. package/dist/core/index.native.js.map +1 -1
  33. package/dist/datetime/index.d.ts.map +1 -0
  34. package/dist/email/index.d.ts.map +1 -0
  35. package/dist/fake/index.d.ts.map +1 -0
  36. package/dist/file/index.d.ts.map +1 -0
  37. package/dist/lock/core/index.d.ts.map +1 -0
  38. package/dist/lock/redis/index.d.ts.map +1 -0
  39. package/dist/logger/index.d.ts +1 -0
  40. package/dist/logger/index.d.ts.map +1 -0
  41. package/dist/mcp/index.d.ts +820 -0
  42. package/dist/mcp/index.d.ts.map +1 -0
  43. package/dist/mcp/index.js +978 -0
  44. package/dist/mcp/index.js.map +1 -0
  45. package/dist/orm/index.d.ts +180 -107
  46. package/dist/orm/index.d.ts.map +1 -0
  47. package/dist/orm/index.js +260 -174
  48. package/dist/orm/index.js.map +1 -1
  49. package/dist/queue/core/index.d.ts +4 -4
  50. package/dist/queue/core/index.d.ts.map +1 -0
  51. package/dist/queue/redis/index.d.ts.map +1 -0
  52. package/dist/redis/index.d.ts.map +1 -0
  53. package/dist/retry/index.d.ts.map +1 -0
  54. package/dist/router/index.d.ts.map +1 -0
  55. package/dist/scheduler/index.d.ts.map +1 -0
  56. package/dist/security/index.d.ts.map +1 -0
  57. package/dist/server/auth/index.d.ts +155 -155
  58. package/dist/server/auth/index.d.ts.map +1 -0
  59. package/dist/server/cache/index.d.ts.map +1 -0
  60. package/dist/server/compress/index.d.ts.map +1 -0
  61. package/dist/server/cookies/index.d.ts.map +1 -0
  62. package/dist/server/core/index.d.ts.map +1 -0
  63. package/dist/server/cors/index.d.ts.map +1 -0
  64. package/dist/server/health/index.d.ts.map +1 -0
  65. package/dist/server/helmet/index.d.ts.map +1 -0
  66. package/dist/server/links/index.d.ts +33 -33
  67. package/dist/server/links/index.d.ts.map +1 -0
  68. package/dist/server/metrics/index.d.ts.map +1 -0
  69. package/dist/server/multipart/index.d.ts.map +1 -0
  70. package/dist/server/proxy/index.d.ts.map +1 -0
  71. package/dist/server/rate-limit/index.d.ts.map +1 -0
  72. package/dist/server/security/index.d.ts +9 -9
  73. package/dist/server/security/index.d.ts.map +1 -0
  74. package/dist/server/static/index.d.ts.map +1 -0
  75. package/dist/server/swagger/index.d.ts.map +1 -0
  76. package/dist/sms/index.d.ts.map +1 -0
  77. package/dist/thread/index.d.ts.map +1 -0
  78. package/dist/topic/core/index.d.ts.map +1 -0
  79. package/dist/topic/redis/index.d.ts.map +1 -0
  80. package/dist/vite/index.d.ts +10 -2
  81. package/dist/vite/index.d.ts.map +1 -0
  82. package/dist/vite/index.js +36 -14
  83. package/dist/vite/index.js.map +1 -1
  84. package/dist/websocket/index.d.ts.map +1 -0
  85. package/package.json +9 -4
  86. package/src/cli/apps/AlephaCli.ts +2 -0
  87. package/src/cli/apps/AlephaPackageBuilderCli.ts +12 -8
  88. package/src/cli/assets/mainTs.ts +9 -10
  89. package/src/cli/commands/ChangelogCommands.ts +389 -0
  90. package/src/cli/commands/DrizzleCommands.ts +204 -4
  91. package/src/cli/commands/ViteCommands.ts +26 -16
  92. package/src/cli/services/AlephaCliUtils.ts +23 -150
  93. package/src/command/providers/CliProvider.ts +76 -5
  94. package/src/core/providers/SchemaValidator.ts +23 -1
  95. package/src/mcp/errors/McpError.ts +72 -0
  96. package/src/mcp/helpers/jsonrpc.ts +163 -0
  97. package/src/mcp/index.ts +132 -0
  98. package/src/mcp/interfaces/McpTypes.ts +248 -0
  99. package/src/mcp/primitives/$prompt.ts +188 -0
  100. package/src/mcp/primitives/$resource.ts +171 -0
  101. package/src/mcp/primitives/$tool.ts +285 -0
  102. package/src/mcp/providers/McpServerProvider.ts +382 -0
  103. package/src/mcp/transports/SseMcpTransport.ts +172 -0
  104. package/src/mcp/transports/StdioMcpTransport.ts +126 -0
  105. package/src/orm/index.ts +12 -0
  106. package/src/orm/providers/drivers/CloudflareD1Provider.ts +164 -0
  107. package/src/orm/providers/drivers/NodeSqliteProvider.ts +3 -1
  108. package/src/vite/plugins/viteAlephaBuild.ts +8 -2
  109. package/src/vite/plugins/viteAlephaDev.ts +6 -2
  110. package/src/vite/tasks/buildServer.ts +1 -1
  111. package/src/vite/tasks/generateCloudflare.ts +43 -15
  112. package/src/vite/tasks/runAlepha.ts +1 -0
package/dist/cli/index.js CHANGED
@@ -1,13 +1,15 @@
1
+ import { createRequire } from "node:module";
1
2
  import { join } from "node:path";
2
3
  import { $env, $hook, $inject, $module, Alepha, AlephaError, OPTIONS, t } from "alepha";
3
4
  import { FileSystemProvider } from "alepha/file";
4
5
  import { $command, CliProvider } from "alepha/command";
5
6
  import { $logger } from "alepha/logger";
6
- import { spawn } from "node:child_process";
7
+ import { exec, spawn } from "node:child_process";
7
8
  import { access, mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
8
9
  import { boot, buildClient, buildServer, copyAssets, generateCloudflare, generateDocker, generateSitemap, generateVercel, prerenderPages } from "alepha/vite";
9
10
  import { tsImport } from "tsx/esm/api";
10
11
  import { readFileSync } from "node:fs";
12
+ import { promisify } from "node:util";
11
13
  import * as os from "node:os";
12
14
 
13
15
  //#region ../../src/cli/assets/appRouterTs.ts
@@ -115,18 +117,17 @@ run(alepha);
115
117
  //#endregion
116
118
  //#region ../../src/cli/assets/mainTs.ts
117
119
  const mainTs = () => `
118
- import { Alepha, run } from "alepha";
119
- import { $logger } from "alepha/logger";
120
-
121
- const alepha = Alepha.create();
122
-
123
- alepha.with(() => {
124
- const log = $logger();
120
+ import { run } from "alepha";
121
+ import { $route } from "alepha/server";
125
122
 
126
- log.info("Hello from Alepha!");
127
- });
123
+ class App {
124
+ root = $route({
125
+ path: "/",
126
+ handler: () => "Hello, Alepha!",
127
+ });
128
+ }
128
129
 
129
- run(alepha);
130
+ run(App);
130
131
  `.trim();
131
132
 
132
133
  //#endregion
@@ -455,88 +456,27 @@ ${models.map((it) => `export const ${it} = models["${it}"];`).join("\n")}
455
456
  `.trim();
456
457
  }
457
458
  /**
458
- * Prepare Drizzle configuration files for a database provider.
459
- *
460
- * Creates temporary entities.js and drizzle.config.js files needed
461
- * for Drizzle Kit commands to run properly.
459
+ * Load environment variables from a .env file.
462
460
  *
463
- * @param options - Configuration options including kit, provider info, and paths
464
- * @returns Path to the generated drizzle.config.js file
461
+ * Reads the .env file in the specified root directory and sets
462
+ * the environment variables in process.env.
465
463
  */
466
- async prepareDrizzleConfig(options) {
467
- const models = Object.keys(options.kit.getModels(options.provider));
468
- const entitiesJs = this.generateEntitiesJs(options.entry, options.providerName, models);
469
- const config = {
470
- schema: await this.writeConfigFile("entities.js", entitiesJs, options.rootDir),
471
- out: `./migrations/${options.providerName}`,
472
- dialect: options.dialect,
473
- dbCredentials: { url: options.providerUrl }
474
- };
475
- if (options.dialect === "sqlite") {
476
- let url = options.providerUrl;
477
- url = url.replace("sqlite://", "").replace("file://", "");
478
- url = join(options.rootDir, url);
479
- config.dbCredentials = { url };
480
- }
481
- if (options.providerName === "pglite") config.driver = "pglite";
482
- const drizzleConfigJs = `export default ${JSON.stringify(config, null, 2)}`;
483
- return await this.writeConfigFile("drizzle.config.js", drizzleConfigJs, options.rootDir);
484
- }
485
- async loadEnvFile(root) {
486
- const envPath = join(root, ".env");
487
- try {
488
- const lines = (await readFile(envPath, "utf8")).split("\n");
489
- for (const line of lines) {
490
- const [key, ...rest] = line.split("=");
491
- if (key) {
492
- const value = rest.join("=");
493
- process.env[key.trim()] = value.trim();
464
+ async loadEnvFile(root, files = [".env"]) {
465
+ for (const it of files) for (const file of [it, `${it}.local`]) {
466
+ const envPath = join(root, file);
467
+ try {
468
+ const lines = (await readFile(envPath, "utf8")).split("\n");
469
+ for (const line of lines) {
470
+ const [key, ...rest] = line.split("=");
471
+ if (key) {
472
+ const value = rest.join("=");
473
+ process.env[key.trim()] = value.trim();
474
+ }
494
475
  }
476
+ this.log.debug(`Loaded environment variables from ${envPath}`);
477
+ } catch {
478
+ this.log.debug(`No ${file} file found at ${envPath}, skipping load.`);
495
479
  }
496
- this.log.debug(`Loaded environment variables from ${envPath}`);
497
- } catch {
498
- this.log.debug(`No .env file found at ${envPath}, skipping load.`);
499
- }
500
- }
501
- /**
502
- * Run a drizzle-kit command for all database providers in an Alepha instance.
503
- *
504
- * Iterates through all repository providers, prepares Drizzle config for each,
505
- * and executes the specified drizzle-kit command.
506
- *
507
- * @param options - Configuration including command to run, flags, and logging
508
- */
509
- async runDrizzleKitCommand(options) {
510
- const rootDir = options.root;
511
- await this.loadEnvFile(rootDir);
512
- this.log.debug(`Using project root: ${rootDir}`);
513
- const { alepha, entry } = await this.loadAlephaFromServerEntryFile(rootDir, options.args);
514
- const drizzleKitProvider = alepha.inject("DrizzleKitProvider");
515
- const repositoryProvider = alepha.inject("RepositoryProvider");
516
- const accepted = /* @__PURE__ */ new Set([]);
517
- for (const primitive of repositoryProvider.getRepositories()) {
518
- const provider = primitive.provider;
519
- const providerName = provider.name;
520
- const dialect = provider.dialect;
521
- if (accepted.has(providerName)) continue;
522
- accepted.add(providerName);
523
- if (options.provider && options.provider !== providerName) {
524
- this.log.debug(`Skipping provider '${providerName}' (filter: ${options.provider})`);
525
- continue;
526
- }
527
- this.log.info("");
528
- this.log.info(options.logMessage(providerName, dialect));
529
- const drizzleConfigJsPath = await this.prepareDrizzleConfig({
530
- kit: drizzleKitProvider,
531
- provider,
532
- providerName,
533
- providerUrl: provider.url,
534
- dialect,
535
- entry,
536
- rootDir
537
- });
538
- const flags = options.commandFlags ? ` ${options.commandFlags}` : "";
539
- await this.exec(`drizzle-kit ${options.command} --config=${drizzleConfigJsPath}${flags}`, { env: { NODE_OPTIONS: "--import tsx" } });
540
480
  }
541
481
  }
542
482
  async getPackageManager(root, flags) {
@@ -685,6 +625,231 @@ var BiomeCommands = class {
685
625
  });
686
626
  };
687
627
 
628
+ //#endregion
629
+ //#region ../../src/cli/commands/ChangelogCommands.ts
630
+ const execAsync = promisify(exec);
631
+ const DEFAULT_IGNORE = [
632
+ "project",
633
+ "release",
634
+ "starter",
635
+ "example",
636
+ "chore",
637
+ "ci",
638
+ "build",
639
+ "test",
640
+ "style"
641
+ ];
642
+ function parseCommit(line, config) {
643
+ const match = line.match(/^([a-f0-9]+)\s+(.+)$/);
644
+ if (!match) return null;
645
+ const [, hash, message] = match;
646
+ const breaking = message.includes("!:") || message.toLowerCase().includes("breaking");
647
+ const ignore = config.ignore ?? DEFAULT_IGNORE;
648
+ const conventionalMatch = message.match(/^(feat|fix|docs|refactor|perf|revert)(?:\(([^)]+)\))?!?:\s*(.+)$/i);
649
+ if (conventionalMatch) {
650
+ const [, type, scope, description] = conventionalMatch;
651
+ if (scope) {
652
+ const baseScope = scope.split("/")[0];
653
+ if (ignore.includes(baseScope) || ignore.includes(scope)) return null;
654
+ }
655
+ if (!scope && ignore.includes(type.toLowerCase())) return null;
656
+ return {
657
+ hash: hash.substring(0, 8),
658
+ type: type.toLowerCase(),
659
+ scope: scope || null,
660
+ description: description.trim(),
661
+ breaking
662
+ };
663
+ }
664
+ const moduleMatch = message.match(/^([a-z][a-z0-9-]*(?:\/[a-z][a-z0-9-]*)?):\s*(.+)$/i);
665
+ if (moduleMatch) {
666
+ const [, module, description] = moduleMatch;
667
+ const baseModule = module.split("/")[0];
668
+ if (ignore.includes(baseModule)) return null;
669
+ if (config.scopes && !config.scopes.includes(baseModule)) return null;
670
+ const desc = description.toLowerCase();
671
+ let type = "improve";
672
+ if (desc.includes("fix") || desc.includes("bug") || desc.includes("issue")) type = "fix";
673
+ else if (desc.includes("add") || desc.includes("new") || desc.includes("implement")) type = "feat";
674
+ return {
675
+ hash: hash.substring(0, 8),
676
+ type,
677
+ scope: module,
678
+ description: description.trim(),
679
+ breaking
680
+ };
681
+ }
682
+ return null;
683
+ }
684
+ function formatCommit(commit) {
685
+ return `- ${commit.scope ? `**${commit.scope}**: ` : ""}${commit.description} (\`${commit.hash}\`)`;
686
+ }
687
+ function generateChangelog(entries) {
688
+ let output = "# Changelog\n\n";
689
+ output += "All notable changes to this project will be documented in this file.\n\n";
690
+ for (const entry of entries) {
691
+ output += `## [${entry.version}] - ${entry.date}\n\n`;
692
+ output += formatEntry(entry);
693
+ }
694
+ return output;
695
+ }
696
+ function formatEntry(entry) {
697
+ let output = "";
698
+ if (entry.breaking.length > 0) {
699
+ output += "### Breaking Changes\n\n";
700
+ for (const commit of entry.breaking) output += `${formatCommit(commit)}\n`;
701
+ output += "\n";
702
+ }
703
+ if (entry.features.length > 0) {
704
+ output += "### Features\n\n";
705
+ for (const commit of entry.features) output += `${formatCommit(commit)}\n`;
706
+ output += "\n";
707
+ }
708
+ if (entry.fixes.length > 0) {
709
+ output += "### Bug Fixes\n\n";
710
+ for (const commit of entry.fixes) output += `${formatCommit(commit)}\n`;
711
+ output += "\n";
712
+ }
713
+ return output;
714
+ }
715
+ async function loadConfig(root) {
716
+ try {
717
+ const pkgPath = join(root, "package.json");
718
+ return JSON.parse(await readFile(pkgPath, "utf8")).changelog ?? {};
719
+ } catch {
720
+ return {};
721
+ }
722
+ }
723
+ var ChangelogCommands = class {
724
+ changelog = $command({
725
+ name: "changelog",
726
+ description: "Generate CHANGELOG.md from git commits",
727
+ flags: t.object({
728
+ release: t.optional(t.boolean({
729
+ when: ["--release", "-r"],
730
+ description: "Output release notes for the latest version only (for GitHub Release)"
731
+ })),
732
+ preview: t.optional(t.boolean({
733
+ when: ["--preview", "-p"],
734
+ description: "Preview unreleased changes (commits since last tag)"
735
+ })),
736
+ output: t.optional(t.string({
737
+ when: ["--output", "-o"],
738
+ description: "Output file path (defaults to CHANGELOG.md, use - for stdout)"
739
+ })),
740
+ limit: t.optional(t.number({
741
+ when: ["--limit", "-l"],
742
+ description: "Limit number of versions to include"
743
+ }))
744
+ }),
745
+ handler: async ({ flags, run, root }) => {
746
+ const config = await loadConfig(root);
747
+ const git = async (cmd) => {
748
+ const { stdout } = await execAsync(`git ${cmd}`, { cwd: root });
749
+ return stdout;
750
+ };
751
+ const tags = (await git("tag --sort=-version:refname")).trim().split("\n").filter((tag) => tag.match(/^\d+\.\d+\.\d+$/));
752
+ if (tags.length === 0) throw new Error("No version tags found");
753
+ if (flags.preview) {
754
+ const latestTag = tags[0];
755
+ const commitsOutput = await git(`log ${latestTag}..HEAD --oneline`);
756
+ if (!commitsOutput.trim()) {
757
+ console.log("No unreleased changes since", latestTag);
758
+ return;
759
+ }
760
+ const entry = {
761
+ version: "Unreleased",
762
+ date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
763
+ features: [],
764
+ fixes: [],
765
+ docs: [],
766
+ improvements: [],
767
+ breaking: []
768
+ };
769
+ for (const line of commitsOutput.trim().split("\n")) {
770
+ if (!line.trim()) continue;
771
+ const commit = parseCommit(line, config);
772
+ if (!commit) continue;
773
+ if (commit.breaking) entry.breaking.push(commit);
774
+ switch (commit.type) {
775
+ case "feat":
776
+ entry.features.push(commit);
777
+ break;
778
+ case "fix":
779
+ entry.fixes.push(commit);
780
+ break;
781
+ case "docs":
782
+ entry.docs.push(commit);
783
+ break;
784
+ case "refactor":
785
+ case "perf":
786
+ case "improve":
787
+ entry.improvements.push(commit);
788
+ break;
789
+ }
790
+ }
791
+ if (!(entry.features.length > 0 || entry.fixes.length > 0 || entry.breaking.length > 0)) {
792
+ console.log("No public changes since", latestTag);
793
+ return;
794
+ }
795
+ console.log(`## [Unreleased] - since ${latestTag}\n`);
796
+ console.log(formatEntry(entry));
797
+ return;
798
+ }
799
+ const entries = [];
800
+ const limit = flags.limit || (flags.release ? 1 : tags.length);
801
+ for (let i = 0; i < Math.min(limit, tags.length); i++) {
802
+ const tag = tags[i];
803
+ const prevTag = tags[i + 1];
804
+ const date = (await git(`log -1 --format=%ci ${tag}`)).trim().split(" ")[0];
805
+ const commitsOutput = await git(`log ${prevTag ? `${prevTag}..${tag}` : tag} --oneline`);
806
+ const entry = {
807
+ version: tag,
808
+ date,
809
+ features: [],
810
+ fixes: [],
811
+ docs: [],
812
+ improvements: [],
813
+ breaking: []
814
+ };
815
+ for (const line of commitsOutput.trim().split("\n")) {
816
+ if (!line.trim()) continue;
817
+ const commit = parseCommit(line, config);
818
+ if (!commit) continue;
819
+ if (commit.breaking) entry.breaking.push(commit);
820
+ switch (commit.type) {
821
+ case "feat":
822
+ entry.features.push(commit);
823
+ break;
824
+ case "fix":
825
+ entry.fixes.push(commit);
826
+ break;
827
+ case "docs":
828
+ entry.docs.push(commit);
829
+ break;
830
+ case "refactor":
831
+ case "perf":
832
+ case "improve":
833
+ entry.improvements.push(commit);
834
+ break;
835
+ }
836
+ }
837
+ if (entry.features.length > 0 || entry.fixes.length > 0 || entry.breaking.length > 0) entries.push(entry);
838
+ }
839
+ if (entries.length === 0) {
840
+ console.log("No public commits found");
841
+ return;
842
+ }
843
+ let output;
844
+ if (flags.release) output = formatEntry(entries[0]);
845
+ else output = generateChangelog(entries);
846
+ const outputPath = flags.output ?? "CHANGELOG.md";
847
+ if (outputPath === "-") console.log(output);
848
+ else await run(`Writing ${outputPath}`, () => writeFile(join(root, outputPath), output, "utf8"));
849
+ }
850
+ });
851
+ };
852
+
688
853
  //#endregion
689
854
  //#region ../../src/cli/commands/CoreCommands.ts
690
855
  var CoreCommands = class {
@@ -770,7 +935,10 @@ var CoreCommands = class {
770
935
 
771
936
  //#endregion
772
937
  //#region ../../src/cli/commands/DrizzleCommands.ts
773
- const drizzleCommandFlags = t.object({ provider: t.optional(t.text({ description: "Database provider name to target (e.g., 'postgres', 'sqlite')" })) });
938
+ const drizzleCommandFlags = t.object({
939
+ provider: t.optional(t.text({ description: "Database provider name to target (e.g., 'postgres', 'sqlite')" })),
940
+ mode: t.optional(t.text({ description: "Environment variable file(s) to load (e.g., 'production' to load .env.production) https://vite.dev/guide/env-and-mode" }))
941
+ });
774
942
  var DrizzleCommands = class {
775
943
  log = $logger();
776
944
  utils = $inject(AlephaCliUtils);
@@ -855,12 +1023,13 @@ var DrizzleCommands = class {
855
1023
  flags: t.extend(drizzleCommandFlags, { custom: t.optional(t.text({ description: "Custom migration name for drizzle-kit generate --custom" })) }),
856
1024
  handler: async ({ args, flags, root }) => {
857
1025
  const commandFlags = flags.custom ? `--custom=${flags.custom}` : void 0;
858
- await this.utils.runDrizzleKitCommand({
1026
+ await this.runDrizzleKitCommand({
859
1027
  root,
860
1028
  args,
861
1029
  command: "generate",
862
1030
  commandFlags,
863
1031
  provider: flags.provider,
1032
+ env: flags.mode,
864
1033
  logMessage: (providerName, dialect) => `Generate '${providerName}' migrations (${dialect}) ...`
865
1034
  });
866
1035
  }
@@ -883,11 +1052,12 @@ var DrizzleCommands = class {
883
1052
  })),
884
1053
  flags: drizzleCommandFlags,
885
1054
  handler: async ({ root, args, flags }) => {
886
- await this.utils.runDrizzleKitCommand({
1055
+ await this.runDrizzleKitCommand({
887
1056
  root,
888
1057
  args,
889
1058
  command: "push",
890
1059
  provider: flags.provider,
1060
+ env: flags.mode,
891
1061
  logMessage: (providerName, dialect) => `Push '${providerName}' schema (${dialect}) ...`
892
1062
  });
893
1063
  }
@@ -910,11 +1080,12 @@ var DrizzleCommands = class {
910
1080
  })),
911
1081
  flags: drizzleCommandFlags,
912
1082
  handler: async ({ root, args, flags }) => {
913
- await this.utils.runDrizzleKitCommand({
1083
+ await this.runDrizzleKitCommand({
914
1084
  root,
915
1085
  args,
916
1086
  command: "migrate",
917
1087
  provider: flags.provider,
1088
+ env: flags.mode,
918
1089
  logMessage: (providerName, dialect) => `Migrate '${providerName}' database (${dialect}) ...`
919
1090
  });
920
1091
  }
@@ -937,15 +1108,102 @@ var DrizzleCommands = class {
937
1108
  })),
938
1109
  flags: drizzleCommandFlags,
939
1110
  handler: async ({ root, args, flags }) => {
940
- await this.utils.runDrizzleKitCommand({
1111
+ await this.runDrizzleKitCommand({
941
1112
  root,
942
1113
  args,
943
1114
  command: "studio",
944
1115
  provider: flags.provider,
1116
+ env: flags.mode,
945
1117
  logMessage: (providerName, dialect) => `Launch Studio for '${providerName}' (${dialect}) ...`
946
1118
  });
947
1119
  }
948
1120
  });
1121
+ /**
1122
+ * Run a drizzle-kit command for all database providers in an Alepha instance.
1123
+ *
1124
+ * Iterates through all repository providers, prepares Drizzle config for each,
1125
+ * and executes the specified drizzle-kit command.
1126
+ *
1127
+ * @param options - Configuration including command to run, flags, and logging
1128
+ */
1129
+ async runDrizzleKitCommand(options) {
1130
+ const rootDir = options.root;
1131
+ const envFiles = [".env"];
1132
+ if (options.env) envFiles.push(`.env.${options.env}`);
1133
+ await this.utils.loadEnvFile(rootDir, envFiles);
1134
+ this.log.debug(`Using project root: ${rootDir}`);
1135
+ const { alepha, entry } = await this.utils.loadAlephaFromServerEntryFile(rootDir, options.args);
1136
+ const drizzleKitProvider = alepha.inject("DrizzleKitProvider");
1137
+ const repositoryProvider = alepha.inject("RepositoryProvider");
1138
+ const accepted = /* @__PURE__ */ new Set([]);
1139
+ for (const primitive of repositoryProvider.getRepositories()) {
1140
+ const provider = primitive.provider;
1141
+ const providerName = provider.name;
1142
+ const dialect = provider.dialect;
1143
+ if (accepted.has(providerName)) continue;
1144
+ accepted.add(providerName);
1145
+ if (options.provider && options.provider !== providerName) {
1146
+ this.log.debug(`Skipping provider '${providerName}' (filter: ${options.provider})`);
1147
+ continue;
1148
+ }
1149
+ this.log.info("");
1150
+ this.log.info(options.logMessage(providerName, dialect));
1151
+ const drizzleConfigJsPath = await this.prepareDrizzleConfig({
1152
+ kit: drizzleKitProvider,
1153
+ provider,
1154
+ providerName,
1155
+ providerUrl: provider.url,
1156
+ dialect,
1157
+ entry,
1158
+ rootDir
1159
+ });
1160
+ const flags = options.commandFlags ? ` ${options.commandFlags}` : "";
1161
+ await this.utils.exec(`drizzle-kit ${options.command} --config=${drizzleConfigJsPath}${flags}`, { env: { NODE_OPTIONS: "--import tsx" } });
1162
+ }
1163
+ }
1164
+ /**
1165
+ * Prepare Drizzle configuration files for a database provider.
1166
+ *
1167
+ * Creates temporary entities.js and drizzle.config.js files needed
1168
+ * for Drizzle Kit commands to run properly.
1169
+ *
1170
+ * @param options - Configuration options including kit, provider info, and paths
1171
+ * @returns Path to the generated drizzle.config.js file
1172
+ */
1173
+ async prepareDrizzleConfig(options) {
1174
+ const models = Object.keys(options.kit.getModels(options.provider));
1175
+ const entitiesJs = this.utils.generateEntitiesJs(options.entry, options.providerName, models);
1176
+ const config = {
1177
+ schema: await this.utils.writeConfigFile("entities.js", entitiesJs, options.rootDir),
1178
+ out: `./migrations/${options.providerName}`,
1179
+ dialect: options.dialect,
1180
+ dbCredentials: { url: options.providerUrl }
1181
+ };
1182
+ if (options.providerName === "d1") config.driver = "d1-http";
1183
+ if (options.providerName === "pglite") config.driver = "pglite";
1184
+ if (options.dialect === "sqlite") if (options.providerName === "d1") {
1185
+ const token = process.env.CLOUDFLARE_API_TOKEN;
1186
+ if (!token) throw new AlephaError("CLOUDFLARE_API_TOKEN environment variable is not set. https://orm.drizzle.team/docs/guides/d1-http-with-drizzle-kit");
1187
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
1188
+ if (!accountId) throw new AlephaError("CLOUDFLARE_ACCOUNT_ID environment variable is not set. https://orm.drizzle.team/docs/guides/d1-http-with-drizzle-kit");
1189
+ const url = options.providerUrl;
1190
+ if (!url.startsWith("cloudflare-d1://")) throw new AlephaError("D1 provider URL must start with 'cloudflare-d1://'.");
1191
+ const [, databaseId] = url.replace("cloudflare-d1://", "").replace("cloudflare-d1:", "").split(":");
1192
+ if (!databaseId) throw new AlephaError("Database ID is missing in the D1 provider URL. Cloudflare D1 URL format: cloudflare-d1://<database_name>:<database_id>");
1193
+ config.dbCredentials = {
1194
+ accountId,
1195
+ databaseId,
1196
+ token
1197
+ };
1198
+ } else {
1199
+ let url = options.providerUrl;
1200
+ url = url.replace("sqlite://", "").replace("file://", "");
1201
+ url = join(options.rootDir, url);
1202
+ config.dbCredentials = { url };
1203
+ }
1204
+ const drizzleConfigJs = `export default ${JSON.stringify(config, null, 2)}`;
1205
+ return await this.utils.writeConfigFile("drizzle.config.js", drizzleConfigJs, options.rootDir);
1206
+ }
949
1207
  };
950
1208
 
951
1209
  //#endregion
@@ -1072,6 +1330,7 @@ var ViteCommands = class {
1072
1330
  }),
1073
1331
  handler: async ({ flags, args, run, root }) => {
1074
1332
  process.env.ALEPHA_BUILD_MODE = "cli";
1333
+ process.env.NODE_ENV = "production";
1075
1334
  if (await this.utils.hasExpo(root)) return;
1076
1335
  await this.utils.ensureConfig(root, {
1077
1336
  viteConfigTs: true,
@@ -1083,7 +1342,8 @@ var ViteCommands = class {
1083
1342
  const clientDir = "public";
1084
1343
  await this.utils.ensureDependency(root, "vite", { run });
1085
1344
  await run.rm("dist", { alias: "clean dist" });
1086
- const viteAlephaBuildOptions = (await import(join(root, "vite.config.ts")))?.default?.plugins.find((it) => !!it[OPTIONS])?.[OPTIONS] ?? {};
1345
+ const viteAlephaBuildOptions = (await createRequire(import.meta.url)("vite").resolveConfig({}, "build", "production")).plugins.find((it) => it.name === "alepha:build")?.[OPTIONS] || {};
1346
+ await this.utils.loadEnvFile(root, [".env", ".env.production"]);
1087
1347
  const stats = flags.stats ?? viteAlephaBuildOptions.stats ?? false;
1088
1348
  const hasServer = viteAlephaBuildOptions.serverEntry !== false;
1089
1349
  let hasClient = false;
@@ -1091,12 +1351,14 @@ var ViteCommands = class {
1091
1351
  await access(join(root, "index.html"));
1092
1352
  hasClient = true;
1093
1353
  } catch {}
1354
+ const clientOptions = typeof viteAlephaBuildOptions.client === "object" ? viteAlephaBuildOptions.client : {};
1094
1355
  if (hasClient) await run({
1095
1356
  name: "vite build client",
1096
1357
  handler: () => buildClient({
1097
1358
  silent: true,
1098
1359
  dist: `${distDir}/${clientDir}`,
1099
- stats
1360
+ stats,
1361
+ precompress: clientOptions.precompress
1100
1362
  })
1101
1363
  });
1102
1364
  await run({
@@ -1124,7 +1386,7 @@ var ViteCommands = class {
1124
1386
  run
1125
1387
  });
1126
1388
  if (hasClient) {
1127
- const sitemapBaseUrl = flags.sitemap ?? (typeof viteAlephaBuildOptions.client === "object" ? viteAlephaBuildOptions.client.sitemap?.hostname : void 0);
1389
+ const sitemapBaseUrl = flags.sitemap ?? clientOptions.sitemap?.hostname;
1128
1390
  if (sitemapBaseUrl) await run({
1129
1391
  name: "add sitemap",
1130
1392
  handler: async () => {
@@ -1134,12 +1396,13 @@ var ViteCommands = class {
1134
1396
  }));
1135
1397
  }
1136
1398
  });
1137
- if (flags.prerender ?? (typeof viteAlephaBuildOptions.client === "object" ? viteAlephaBuildOptions.client.prerender : false)) await run({
1399
+ if (flags.prerender ?? clientOptions.prerender) await run({
1138
1400
  name: "pre-render pages",
1139
1401
  handler: async () => {
1140
1402
  await prerenderPages({
1141
1403
  dist: `${distDir}/${clientDir}`,
1142
- entry: `${distDir}/index.js`
1404
+ entry: `${distDir}/index.js`,
1405
+ compress: clientOptions.precompress
1143
1406
  });
1144
1407
  }
1145
1408
  });
@@ -1155,10 +1418,16 @@ var ViteCommands = class {
1155
1418
  })
1156
1419
  });
1157
1420
  }
1158
- if (flags.cloudflare || viteAlephaBuildOptions.cloudflare) await run({
1159
- name: "add Cloudflare config",
1160
- handler: () => generateCloudflare({ distDir })
1161
- });
1421
+ if (flags.cloudflare || viteAlephaBuildOptions.cloudflare) {
1422
+ const config = typeof viteAlephaBuildOptions.cloudflare === "boolean" ? {} : viteAlephaBuildOptions.cloudflare;
1423
+ await run({
1424
+ name: "add Cloudflare config",
1425
+ handler: () => generateCloudflare({
1426
+ distDir,
1427
+ config
1428
+ })
1429
+ });
1430
+ }
1162
1431
  if (flags.docker || viteAlephaBuildOptions.docker) {
1163
1432
  const dockerConfig = typeof viteAlephaBuildOptions.docker === "object" ? viteAlephaBuildOptions.docker : {};
1164
1433
  await run({
@@ -1205,6 +1474,7 @@ const AlephaCli = $module({
1205
1474
  name: "alepha.cli",
1206
1475
  services: [
1207
1476
  AlephaCliExtension,
1477
+ ChangelogCommands,
1208
1478
  CoreCommands,
1209
1479
  DrizzleCommands,
1210
1480
  VerifyCommands,
@@ -1251,11 +1521,8 @@ var AlephaPackageBuilderCli = class {
1251
1521
  const tmpDir = join(root, "node_modules/.alepha");
1252
1522
  await this.fs.mkdir(tmpDir, { recursive: true }).catch(() => {});
1253
1523
  await this.fs.writeFile(join(tmpDir, "module-dependencies.json"), JSON.stringify(modules, null, 2));
1254
- const external = [
1255
- "alepha",
1256
- packageName,
1257
- ...modules.map((item) => `${packageName}/${item.name.replace("-", "/").replace("/core", "")}`)
1258
- ];
1524
+ const tsconfig = await readFile(join(root, "../../tsconfig.json"), "utf-8");
1525
+ const external = Object.keys(JSON.parse(tsconfig).compilerOptions.paths);
1259
1526
  await run.rm(this.dist);
1260
1527
  const build = async (item) => {
1261
1528
  const entries = [];
@@ -1268,7 +1535,11 @@ var AlephaPackageBuilderCli = class {
1268
1535
  sourcemap: true,
1269
1536
  fixedExtension: false,
1270
1537
  platform: "node",
1271
- external
1538
+ external,
1539
+ dts: {
1540
+ sourcemap: true,
1541
+ resolve: false
1542
+ }
1272
1543
  });
1273
1544
  if (item.native) entries.push({
1274
1545
  entry: join(src, "index.native.ts"),