alepha 0.14.0 → 0.14.2

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 (149) hide show
  1. package/README.md +3 -3
  2. package/dist/api/audits/index.d.ts +80 -1
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js.map +1 -1
  5. package/dist/api/files/index.d.ts +80 -1
  6. package/dist/api/files/index.d.ts.map +1 -1
  7. package/dist/api/files/index.js.map +1 -1
  8. package/dist/api/jobs/index.d.ts +236 -157
  9. package/dist/api/jobs/index.d.ts.map +1 -1
  10. package/dist/api/jobs/index.js.map +1 -1
  11. package/dist/api/notifications/index.d.ts +21 -1
  12. package/dist/api/notifications/index.d.ts.map +1 -1
  13. package/dist/api/parameters/index.d.ts +451 -4
  14. package/dist/api/parameters/index.d.ts.map +1 -1
  15. package/dist/api/parameters/index.js.map +1 -1
  16. package/dist/api/users/index.d.ts +252 -249
  17. package/dist/api/users/index.d.ts.map +1 -1
  18. package/dist/api/users/index.js +4 -0
  19. package/dist/api/users/index.js.map +1 -1
  20. package/dist/api/verifications/index.d.ts +128 -128
  21. package/dist/api/verifications/index.d.ts.map +1 -1
  22. package/dist/batch/index.js.map +1 -1
  23. package/dist/cache/core/index.js.map +1 -1
  24. package/dist/cli/index.d.ts +304 -115
  25. package/dist/cli/index.d.ts.map +1 -1
  26. package/dist/cli/index.js +650 -531
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/command/index.d.ts +210 -13
  29. package/dist/command/index.d.ts.map +1 -1
  30. package/dist/command/index.js +306 -69
  31. package/dist/command/index.js.map +1 -1
  32. package/dist/core/index.browser.js.map +1 -1
  33. package/dist/core/index.d.ts +1 -1
  34. package/dist/core/index.d.ts.map +1 -1
  35. package/dist/core/index.js +7 -6
  36. package/dist/core/index.js.map +1 -1
  37. package/dist/core/index.native.js +7 -6
  38. package/dist/core/index.native.js.map +1 -1
  39. package/dist/datetime/index.js.map +1 -1
  40. package/dist/fake/index.js.map +1 -1
  41. package/dist/file/index.d.ts.map +1 -1
  42. package/dist/file/index.js.map +1 -1
  43. package/dist/lock/redis/index.js.map +1 -1
  44. package/dist/logger/index.js.map +1 -1
  45. package/dist/mcp/index.js.map +1 -1
  46. package/dist/orm/index.browser.js +26 -5
  47. package/dist/orm/index.browser.js.map +1 -1
  48. package/dist/orm/index.d.ts +294 -215
  49. package/dist/orm/index.d.ts.map +1 -1
  50. package/dist/orm/index.js +522 -523
  51. package/dist/orm/index.js.map +1 -1
  52. package/dist/queue/redis/index.js +2 -4
  53. package/dist/queue/redis/index.js.map +1 -1
  54. package/dist/redis/index.d.ts +400 -29
  55. package/dist/redis/index.d.ts.map +1 -1
  56. package/dist/redis/index.js +412 -21
  57. package/dist/redis/index.js.map +1 -1
  58. package/dist/retry/index.js.map +1 -1
  59. package/dist/router/index.js.map +1 -1
  60. package/dist/scheduler/index.js.map +1 -1
  61. package/dist/security/index.d.ts.map +1 -1
  62. package/dist/security/index.js.map +1 -1
  63. package/dist/server/auth/index.d.ts +155 -155
  64. package/dist/server/auth/index.js.map +1 -1
  65. package/dist/server/cache/index.js.map +1 -1
  66. package/dist/server/cookies/index.browser.js.map +1 -1
  67. package/dist/server/cookies/index.js.map +1 -1
  68. package/dist/server/core/index.browser.js.map +1 -1
  69. package/dist/server/core/index.d.ts +0 -1
  70. package/dist/server/core/index.d.ts.map +1 -1
  71. package/dist/server/core/index.js.map +1 -1
  72. package/dist/server/helmet/index.d.ts +4 -1
  73. package/dist/server/helmet/index.d.ts.map +1 -1
  74. package/dist/server/helmet/index.js.map +1 -1
  75. package/dist/server/links/index.browser.js.map +1 -1
  76. package/dist/server/links/index.js.map +1 -1
  77. package/dist/server/multipart/index.d.ts.map +1 -1
  78. package/dist/server/multipart/index.js.map +1 -1
  79. package/dist/server/proxy/index.js.map +1 -1
  80. package/dist/server/rate-limit/index.js.map +1 -1
  81. package/dist/server/security/index.d.ts +9 -9
  82. package/dist/server/security/index.js.map +1 -1
  83. package/dist/server/swagger/index.js.map +1 -1
  84. package/dist/thread/index.js.map +1 -1
  85. package/dist/topic/core/index.js.map +1 -1
  86. package/dist/topic/redis/index.js +3 -3
  87. package/dist/topic/redis/index.js.map +1 -1
  88. package/dist/vite/index.js +9 -6
  89. package/dist/vite/index.js.map +1 -1
  90. package/dist/websocket/index.browser.js.map +1 -1
  91. package/dist/websocket/index.d.ts +7 -7
  92. package/dist/websocket/index.js.map +1 -1
  93. package/package.json +3 -3
  94. package/src/api/users/index.ts +4 -0
  95. package/src/cli/apps/AlephaCli.ts +36 -14
  96. package/src/cli/apps/AlephaPackageBuilderCli.ts +5 -1
  97. package/src/cli/assets/appRouterTs.ts +1 -1
  98. package/src/cli/atoms/changelogOptions.ts +45 -0
  99. package/src/cli/commands/{ViteCommands.ts → build.ts} +4 -93
  100. package/src/cli/commands/changelog.ts +244 -0
  101. package/src/cli/commands/clean.ts +14 -0
  102. package/src/cli/commands/{DrizzleCommands.ts → db.ts} +37 -124
  103. package/src/cli/commands/deploy.ts +118 -0
  104. package/src/cli/commands/dev.ts +57 -0
  105. package/src/cli/commands/format.ts +17 -0
  106. package/src/cli/commands/{CoreCommands.ts → init.ts} +2 -40
  107. package/src/cli/commands/lint.ts +17 -0
  108. package/src/cli/commands/root.ts +32 -0
  109. package/src/cli/commands/run.ts +24 -0
  110. package/src/cli/commands/test.ts +42 -0
  111. package/src/cli/commands/typecheck.ts +19 -0
  112. package/src/cli/commands/{VerifyCommands.ts → verify.ts} +1 -13
  113. package/src/cli/defineConfig.ts +24 -0
  114. package/src/cli/index.ts +17 -5
  115. package/src/cli/services/AlephaCliUtils.ts +4 -21
  116. package/src/cli/services/GitMessageParser.ts +77 -0
  117. package/src/command/helpers/EnvUtils.ts +37 -0
  118. package/src/command/index.ts +3 -1
  119. package/src/command/primitives/$command.ts +172 -6
  120. package/src/command/providers/CliProvider.ts +424 -91
  121. package/src/core/Alepha.ts +8 -5
  122. package/src/file/providers/NodeFileSystemProvider.ts +3 -1
  123. package/src/orm/index.browser.ts +1 -1
  124. package/src/orm/index.ts +18 -10
  125. package/src/orm/interfaces/PgQueryWhere.ts +1 -26
  126. package/src/orm/providers/{PostgresTypeProvider.ts → DatabaseTypeProvider.ts} +25 -3
  127. package/src/orm/providers/drivers/BunPostgresProvider.ts +225 -0
  128. package/src/orm/providers/drivers/BunSqliteProvider.ts +180 -0
  129. package/src/orm/providers/drivers/DatabaseProvider.ts +25 -0
  130. package/src/orm/providers/drivers/NodePostgresProvider.ts +0 -25
  131. package/src/orm/services/QueryManager.ts +10 -125
  132. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -7
  133. package/src/redis/index.ts +65 -3
  134. package/src/redis/providers/BunRedisProvider.ts +304 -0
  135. package/src/redis/providers/BunRedisSubscriberProvider.ts +94 -0
  136. package/src/redis/providers/NodeRedisProvider.ts +280 -0
  137. package/src/redis/providers/NodeRedisSubscriberProvider.ts +94 -0
  138. package/src/redis/providers/RedisProvider.ts +134 -140
  139. package/src/redis/providers/RedisSubscriberProvider.ts +58 -49
  140. package/src/server/core/providers/BunHttpServerProvider.ts +0 -3
  141. package/src/server/core/providers/ServerBodyParserProvider.ts +3 -1
  142. package/src/server/core/providers/ServerProvider.ts +7 -4
  143. package/src/server/multipart/providers/ServerMultipartProvider.ts +3 -1
  144. package/src/server/proxy/providers/ServerProxyProvider.ts +1 -1
  145. package/src/topic/redis/providers/RedisTopicProvider.ts +3 -3
  146. package/src/vite/tasks/buildServer.ts +1 -0
  147. package/src/cli/commands/BiomeCommands.ts +0 -29
  148. package/src/cli/commands/ChangelogCommands.ts +0 -389
  149. package/src/orm/services/PgJsonQueryManager.ts +0 -511
@@ -1,7 +1,7 @@
1
1
  import { access, readFile, unlink, writeFile } from "node:fs/promises";
2
2
  import { createRequire } from "node:module";
3
3
  import { join } from "node:path";
4
- import { $env, $inject, OPTIONS, t } from "alepha";
4
+ import { $inject, OPTIONS, t } from "alepha";
5
5
  import { $command } from "alepha/command";
6
6
  import { $logger } from "alepha/logger";
7
7
  import {
@@ -18,78 +18,10 @@ import {
18
18
  import type * as Vite from "vite";
19
19
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
20
20
 
21
- export class ViteCommands {
21
+ export class BuildCommand {
22
22
  protected readonly log = $logger();
23
23
  protected readonly utils = $inject(AlephaCliUtils);
24
24
 
25
- protected readonly env = $env(
26
- t.object({
27
- VITEST_ARGS: t.string({ default: "" }),
28
- }),
29
- );
30
-
31
- public readonly run = $command({
32
- name: "run",
33
- hide: true,
34
- description: "Run a TypeScript file directly",
35
- flags: t.object({
36
- watch: t.optional(
37
- t.boolean({ description: "Watch file for changes", alias: "w" }),
38
- ),
39
- }),
40
- summary: false,
41
- args: t.text({ title: "path", description: "Filepath to run" }),
42
- handler: async ({ args, flags, root }) => {
43
- await this.utils.ensureTsConfig(root);
44
- await this.utils.exec(`tsx ${flags.watch ? "watch " : ""}${args}`);
45
- },
46
- });
47
-
48
- /**
49
- * Will run the project in watch mode.
50
- *
51
- * - If an index.html file is found in the project root, it will run Vite in dev mode.
52
- * - Otherwise, it will look for a server entry file and run it with tsx in watch mode.
53
- */
54
- public readonly dev = $command({
55
- name: "dev",
56
- description: "Run the project in development mode",
57
- args: t.optional(t.text({ title: "path", description: "Filepath to run" })),
58
- handler: async ({ args, root }) => {
59
- const expo = await this.utils.hasExpo(root);
60
-
61
- await this.utils.ensureConfig(root, {
62
- viteConfigTs: !expo,
63
- tsconfigJson: true,
64
- });
65
-
66
- if (expo) {
67
- await this.utils.exec(`expo start`);
68
- return;
69
- }
70
-
71
- const entry = await boot.getServerEntry(root, args);
72
- this.log.trace("Entry file found", { entry });
73
-
74
- try {
75
- await access(join(root, "index.html"));
76
- } catch {
77
- this.log.trace("No index.html found, running entry file with tsx");
78
- let cmd = "tsx --watch";
79
- if (await this.utils.exists(root, ".env")) {
80
- cmd += ` --env-file=./.env`;
81
- }
82
- cmd += ` ${entry}`;
83
- await this.utils.exec(cmd);
84
- return;
85
- }
86
-
87
- // Ensure vite is installed before running
88
- await this.utils.ensureDependency(root, "vite");
89
- await this.utils.exec(`vite`);
90
- },
91
- });
92
-
93
25
  public readonly build = $command({
94
26
  name: "build",
95
27
  description: "Build the project for production",
@@ -122,11 +54,6 @@ export class ViteCommands {
122
54
  description: "Generate sitemap.xml with base URL",
123
55
  }),
124
56
  ),
125
- prerender: t.optional(
126
- t.boolean({
127
- description: "Pre-render static pages",
128
- }),
129
- ),
130
57
  }),
131
58
  handler: async ({ flags, args, run, root }) => {
132
59
  // Tell viteAlephaBuild plugin to skip - CLI handles all tasks
@@ -165,7 +92,7 @@ export class ViteCommands {
165
92
  );
166
93
  const viteAlephaBuildOptions = alephaPlugin?.[OPTIONS] || {};
167
94
 
168
- await this.utils.loadEnvFile(root, [".env", ".env.production"]);
95
+ await this.utils.loadEnv(root, [".env", ".env.production"]);
169
96
 
170
97
  const stats = flags.stats ?? viteAlephaBuildOptions.stats ?? false;
171
98
  const hasServer = viteAlephaBuildOptions.serverEntry !== false;
@@ -254,7 +181,7 @@ export class ViteCommands {
254
181
  }
255
182
 
256
183
  // Pre-render static pages
257
- const shouldPrerender = flags.prerender ?? clientOptions.prerender;
184
+ const shouldPrerender = clientOptions.prerender;
258
185
 
259
186
  if (shouldPrerender) {
260
187
  await run({
@@ -318,20 +245,4 @@ export class ViteCommands {
318
245
  }
319
246
  },
320
247
  });
321
-
322
- public readonly test = $command({
323
- name: "test",
324
- description: "Run tests using Vitest",
325
- handler: async ({ root }) => {
326
- await this.utils.ensureConfig(root, {
327
- tsconfigJson: true,
328
- viteConfigTs: true,
329
- });
330
-
331
- // Ensure vitest is installed before running
332
- await this.utils.ensureDependency(root, "vitest");
333
-
334
- await this.utils.exec(`vitest run ${this.env.VITEST_ARGS}`);
335
- },
336
- });
337
248
  }
@@ -0,0 +1,244 @@
1
+ import { exec } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { $inject, $use, t } from "alepha";
4
+ import { $command } from "alepha/command";
5
+ import { $logger } from "alepha/logger";
6
+ import { changelogOptions } from "../atoms/changelogOptions.ts";
7
+ import { GitMessageParser } from "../services/GitMessageParser.ts";
8
+
9
+ export {
10
+ type ChangelogOptions,
11
+ changelogOptions,
12
+ DEFAULT_IGNORE,
13
+ } from "../atoms/changelogOptions.ts";
14
+ export { GitMessageParser } from "../services/GitMessageParser.ts";
15
+
16
+ const execAsync = promisify(exec);
17
+
18
+ // =============================================================================
19
+ // GIT PROVIDER
20
+ // =============================================================================
21
+
22
+ /**
23
+ * Git provider for executing git commands.
24
+ * Can be substituted in tests with a mock implementation.
25
+ */
26
+ export class GitProvider {
27
+ async exec(cmd: string, cwd: string): Promise<string> {
28
+ const { stdout } = await execAsync(`git ${cmd}`, { cwd });
29
+ return stdout;
30
+ }
31
+ }
32
+
33
+ // =============================================================================
34
+ // TYPES
35
+ // =============================================================================
36
+
37
+ export interface Commit {
38
+ hash: string;
39
+ type: string;
40
+ scope: string | null;
41
+ description: string;
42
+ breaking: boolean;
43
+ }
44
+
45
+ interface ChangelogEntry {
46
+ features: Commit[];
47
+ fixes: Commit[];
48
+ }
49
+
50
+ // =============================================================================
51
+ // CHANGELOG COMMAND
52
+ // =============================================================================
53
+
54
+ /**
55
+ * Changelog command for generating release notes from git commits.
56
+ *
57
+ * Usage:
58
+ * - `alepha changelog` - Show unreleased changes since latest tag to HEAD
59
+ * - `alepha changelog --from=1.0.0` - Show changes from version to HEAD
60
+ * - `alepha changelog --from=1.0.0 --to=1.1.0` - Show changes between two refs
61
+ * - `alepha changelog | tee -a CHANGELOG.md` - Append to file
62
+ */
63
+ export class ChangelogCommand {
64
+ protected readonly log = $logger();
65
+ protected readonly git = $inject(GitProvider);
66
+ protected readonly parser = $inject(GitMessageParser);
67
+ protected readonly config = $use(changelogOptions);
68
+
69
+ // ---------------------------------------------------------------------------
70
+ // FORMATTING
71
+ // ---------------------------------------------------------------------------
72
+
73
+ /**
74
+ * Format a single commit line.
75
+ * Example: `- **cli**: add new command (\`abc1234\`)`
76
+ * Breaking changes are flagged: `- **cli**: add new command [BREAKING] (\`abc1234\`)`
77
+ */
78
+ protected formatCommit(commit: Commit): string {
79
+ const breaking = commit.breaking ? " [BREAKING]" : "";
80
+ return `- **${commit.scope}**: ${commit.description}${breaking} (\`${commit.hash}\`)`;
81
+ }
82
+
83
+ /**
84
+ * Format the changelog entry with sections.
85
+ */
86
+ protected formatEntry(entry: ChangelogEntry): string {
87
+ const sections: string[] = [];
88
+
89
+ if (entry.features.length > 0) {
90
+ sections.push("### Features\n");
91
+ for (const commit of entry.features) {
92
+ sections.push(this.formatCommit(commit));
93
+ }
94
+ sections.push("");
95
+ }
96
+
97
+ if (entry.fixes.length > 0) {
98
+ sections.push("### Bug Fixes\n");
99
+ for (const commit of entry.fixes) {
100
+ sections.push(this.formatCommit(commit));
101
+ }
102
+ sections.push("");
103
+ }
104
+
105
+ return sections.join("\n");
106
+ }
107
+
108
+ // ---------------------------------------------------------------------------
109
+ // PARSING
110
+ // ---------------------------------------------------------------------------
111
+
112
+ /**
113
+ * Parse git log output into a changelog entry.
114
+ */
115
+ protected parseCommits(commitsOutput: string): ChangelogEntry {
116
+ const entry: ChangelogEntry = {
117
+ features: [],
118
+ fixes: [],
119
+ };
120
+
121
+ for (const line of commitsOutput.trim().split("\n")) {
122
+ if (!line.trim()) continue;
123
+
124
+ const commit = this.parser.parseCommit(line, this.config);
125
+ if (!commit) {
126
+ this.log.trace("Skipping commit", { line });
127
+ continue;
128
+ }
129
+
130
+ this.log.trace("Parsed commit", { commit });
131
+
132
+ // Categorize commit (breaking flag is preserved on the commit itself)
133
+ if (commit.type === "feat") {
134
+ entry.features.push(commit);
135
+ } else if (commit.type === "fix") {
136
+ entry.fixes.push(commit);
137
+ }
138
+ }
139
+
140
+ return entry;
141
+ }
142
+
143
+ /**
144
+ * Check if entry has any public commits.
145
+ */
146
+ protected hasChanges(entry: ChangelogEntry): boolean {
147
+ return entry.features.length > 0 || entry.fixes.length > 0;
148
+ }
149
+
150
+ /**
151
+ * Get the latest version tag.
152
+ */
153
+ protected async getLatestTag(
154
+ git: (cmd: string) => Promise<string>,
155
+ ): Promise<string | null> {
156
+ const tagsOutput = await git("tag --sort=-version:refname");
157
+ const tags = tagsOutput
158
+ .trim()
159
+ .split("\n")
160
+ .filter((tag) => tag.match(/^\d+\.\d+\.\d+$/));
161
+
162
+ return tags[0] || null;
163
+ }
164
+
165
+ // ---------------------------------------------------------------------------
166
+ // COMMAND
167
+ // ---------------------------------------------------------------------------
168
+
169
+ public readonly changelog = $command({
170
+ name: "changelog",
171
+ description:
172
+ "Generate changelog from conventional commits (outputs to stdout)",
173
+ flags: t.object({
174
+ /**
175
+ * Show changes from this ref (tag, commit, branch).
176
+ * Defaults to the latest version tag.
177
+ * Example: --from=1.0.0
178
+ */
179
+ from: t.optional(
180
+ t.string({
181
+ aliases: ["f"],
182
+ description: "Starting ref (default: latest tag)",
183
+ }),
184
+ ),
185
+ /**
186
+ * Show changes up to this ref (tag, commit, branch).
187
+ * Defaults to HEAD.
188
+ * Example: --to=main
189
+ */
190
+ to: t.optional(
191
+ t.string({
192
+ aliases: ["t"],
193
+ description: "Ending ref (default: HEAD)",
194
+ }),
195
+ ),
196
+ }),
197
+ handler: async ({ flags, root }) => {
198
+ const git = (cmd: string) => this.git.exec(cmd, root);
199
+
200
+ // Determine the starting point
201
+ let fromRef: string;
202
+
203
+ if (flags.from) {
204
+ // User specified a ref
205
+ fromRef = flags.from;
206
+ this.log.debug("Using specified from ref", { from: fromRef });
207
+ } else {
208
+ // Use latest tag
209
+ const latestTag = await this.getLatestTag(git);
210
+ if (!latestTag) {
211
+ process.stdout.write("No version tags found in repository\n");
212
+ return;
213
+ }
214
+ fromRef = latestTag;
215
+ this.log.debug("Using latest tag", { from: fromRef });
216
+ }
217
+
218
+ // Determine the ending point
219
+ const toRef = flags.to || "HEAD";
220
+ this.log.debug("Using to ref", { to: toRef });
221
+
222
+ // Get commits in range
223
+ const commitsOutput = await git(`log ${fromRef}..${toRef} --oneline`);
224
+
225
+ if (!commitsOutput.trim()) {
226
+ process.stdout.write(`No changes in range ${fromRef}..${toRef}\n`);
227
+ return;
228
+ }
229
+
230
+ // Parse and format
231
+ const entry = this.parseCommits(commitsOutput);
232
+
233
+ if (!this.hasChanges(entry)) {
234
+ process.stdout.write(
235
+ `No public changes in range ${fromRef}..${toRef}\n`,
236
+ );
237
+ return;
238
+ }
239
+
240
+ // Output the formatted changelog (no header - caller adds it if needed)
241
+ process.stdout.write(this.formatEntry(entry));
242
+ },
243
+ });
244
+ }
@@ -0,0 +1,14 @@
1
+ import { $command } from "alepha/command";
2
+
3
+ export class CleanCommand {
4
+ /**
5
+ * Clean the project, removing the "dist" directory
6
+ */
7
+ public readonly clean = $command({
8
+ name: "clean",
9
+ description: "Clean the project",
10
+ handler: async ({ run }) => {
11
+ await run.rm("./dist");
12
+ },
13
+ });
14
+ }
@@ -3,7 +3,11 @@ import { join } from "node:path";
3
3
  import { $inject, AlephaError, t } from "alepha";
4
4
  import { $command } from "alepha/command";
5
5
  import { $logger } from "alepha/logger";
6
- import type { DrizzleKitProvider, RepositoryProvider } from "alepha/orm";
6
+ import type {
7
+ DatabaseProvider,
8
+ DrizzleKitProvider,
9
+ RepositoryProvider,
10
+ } from "alepha/orm";
7
11
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
8
12
 
9
13
  const drizzleCommandFlags = t.object({
@@ -21,15 +25,15 @@ const drizzleCommandFlags = t.object({
21
25
  ),
22
26
  });
23
27
 
24
- export class DrizzleCommands {
25
- log = $logger();
26
- utils = $inject(AlephaCliUtils);
28
+ export class DbCommand {
29
+ protected readonly log = $logger();
30
+ protected readonly utils = $inject(AlephaCliUtils);
27
31
 
28
32
  /**
29
33
  * Check if database migrations are up to date.
30
34
  */
31
- check = $command({
32
- name: "db:check-migrations",
35
+ protected readonly check = $command({
36
+ name: "check-migrations",
33
37
  description: "Check if database migration files are up to date",
34
38
  args: t.optional(
35
39
  t.text({
@@ -70,7 +74,7 @@ export class DrizzleCommands {
70
74
  ).catch(() => null);
71
75
 
72
76
  if (!journalFile) {
73
- this.log.info(`No migration journal found.`);
77
+ this.log.info("No migration journal found.");
74
78
  return;
75
79
  }
76
80
 
@@ -126,15 +130,9 @@ export class DrizzleCommands {
126
130
 
127
131
  /**
128
132
  * Generate database migration files
129
- *
130
- * - Loads the Alepha instance from the specified entry file.
131
- * - Retrieves all repository primitives to gather database models.
132
- * - Creates temporary entity definitions based on the current database schema.
133
- * - Writes these definitions to a temporary schema file. (node_modules/.db/entities.ts)
134
- * - Invokes Drizzle Kit's CLI to generate migration files based on the current schema.
135
133
  */
136
- generate = $command({
137
- name: "db:generate",
134
+ protected readonly generate = $command({
135
+ name: "generate",
138
136
  description: "Generate migration files based on current database schema",
139
137
  summary: false,
140
138
  args: t.optional(
@@ -171,14 +169,9 @@ export class DrizzleCommands {
171
169
 
172
170
  /**
173
171
  * Push database schema changes directly to the database
174
- *
175
- * - Loads the Alepha instance from the specified entry file.
176
- * - Retrieves all repository primitives to gather database models.
177
- * - Creates temporary entity definitions and Drizzle config.
178
- * - Invokes Drizzle Kit's push command to apply schema changes directly.
179
172
  */
180
- push = $command({
181
- name: "db:push",
173
+ protected readonly push = $command({
174
+ name: "push",
182
175
  description: "Push database schema changes directly to the database",
183
176
  summary: false,
184
177
  args: t.optional(
@@ -203,14 +196,9 @@ export class DrizzleCommands {
203
196
 
204
197
  /**
205
198
  * Apply pending database migrations
206
- *
207
- * - Loads the Alepha instance from the specified entry file.
208
- * - Retrieves all repository primitives to gather database models.
209
- * - Creates temporary entity definitions and Drizzle config.
210
- * - Invokes Drizzle Kit's migrate command to apply pending migrations.
211
199
  */
212
- migrate = $command({
213
- name: "db:migrate",
200
+ protected readonly migrate = $command({
201
+ name: "migrate",
214
202
  description: "Apply pending database migrations",
215
203
  summary: false,
216
204
  args: t.optional(
@@ -235,14 +223,9 @@ export class DrizzleCommands {
235
223
 
236
224
  /**
237
225
  * Launch Drizzle Studio database browser
238
- *
239
- * - Loads the Alepha instance from the specified entry file.
240
- * - Retrieves all repository primitives to gather database models.
241
- * - Creates temporary entity definitions and Drizzle config.
242
- * - Invokes Drizzle Kit's studio command to launch the web-based database browser.
243
226
  */
244
- studio = $command({
245
- name: "db:studio",
227
+ protected readonly studio = $command({
228
+ name: "studio",
246
229
  description: "Launch Drizzle Studio database browser",
247
230
  summary: false,
248
231
  args: t.optional(
@@ -265,13 +248,20 @@ export class DrizzleCommands {
265
248
  },
266
249
  });
267
250
 
251
+ /**
252
+ * Parent command for database operations.
253
+ */
254
+ public readonly db = $command({
255
+ name: "db",
256
+ description: "Database management commands",
257
+ children: [this.check, this.generate, this.push, this.migrate, this.studio],
258
+ handler: async ({ help }) => {
259
+ help();
260
+ },
261
+ });
262
+
268
263
  /**
269
264
  * Run a drizzle-kit command for all database providers in an Alepha instance.
270
- *
271
- * Iterates through all repository providers, prepares Drizzle config for each,
272
- * and executes the specified drizzle-kit command.
273
- *
274
- * @param options - Configuration including command to run, flags, and logging
275
265
  */
276
266
  public async runDrizzleKitCommand(options: {
277
267
  root: string;
@@ -289,7 +279,7 @@ export class DrizzleCommands {
289
279
  envFiles.push(`.env.${options.env}`);
290
280
  }
291
281
 
292
- await this.utils.loadEnvFile(rootDir, envFiles);
282
+ await this.utils.loadEnv(rootDir, envFiles);
293
283
 
294
284
  this.log.debug(`Using project root: ${rootDir}`);
295
285
 
@@ -349,16 +339,10 @@ export class DrizzleCommands {
349
339
 
350
340
  /**
351
341
  * Prepare Drizzle configuration files for a database provider.
352
- *
353
- * Creates temporary entities.js and drizzle.config.js files needed
354
- * for Drizzle Kit commands to run properly.
355
- *
356
- * @param options - Configuration options including kit, provider info, and paths
357
- * @returns Path to the generated drizzle.config.js file
358
342
  */
359
343
  public async prepareDrizzleConfig(options: {
360
344
  kit: any;
361
- provider: any;
345
+ provider: DatabaseProvider;
362
346
  providerName: string;
363
347
  providerUrl: string;
364
348
  dialect: string;
@@ -387,6 +371,10 @@ export class DrizzleCommands {
387
371
  },
388
372
  };
389
373
 
374
+ if (options.provider.schema) {
375
+ config.schemaFilter = options.provider.schema;
376
+ }
377
+
390
378
  if (options.providerName === "d1") {
391
379
  config.driver = "d1-http";
392
380
  }
@@ -453,79 +441,4 @@ export class DrizzleCommands {
453
441
  options.rootDir,
454
442
  );
455
443
  }
456
-
457
- // /**
458
- // * Drop database schema (development only)
459
- // *
460
- // * @experimental
461
- // */
462
- // drop = $command({
463
- // name: "db:drop",
464
- // description: "Drop database schema (development only)",
465
- // summary: false,
466
- // args: t.optional(
467
- // t.text({
468
- // title: "path",
469
- // description: "Path to the Alepha server entry file",
470
- // }),
471
- // ),
472
- // flags: drizzleCommandFlags,
473
- // handler: async ({ flags }) => {
474
- // // TODO: Implement db:drop
475
- // this.log.warn("db:drop is not yet implemented");
476
- // if (flags.provider) {
477
- // this.log.info(`Provider filter: ${flags.provider}`);
478
- // }
479
- // },
480
- // });
481
- //
482
- // /**
483
- // * Seed database with initial data
484
- // *
485
- // * @experimental
486
- // */
487
- // seed = $command({
488
- // name: "db:seed",
489
- // description: "Seed database with initial data",
490
- // summary: false,
491
- // args: t.optional(
492
- // t.text({
493
- // title: "path",
494
- // description: "Path to the Alepha server entry file",
495
- // }),
496
- // ),
497
- // flags: drizzleCommandFlags,
498
- // handler: async ({ flags }) => {
499
- // // TODO: Implement db:seed
500
- // this.log.warn("db:seed is not yet implemented");
501
- // if (flags.provider) {
502
- // this.log.info(`Provider filter: ${flags.provider}`);
503
- // }
504
- // },
505
- // });
506
- //
507
- // /**
508
- // * Show pending database migrations status
509
- // *
510
- // * @experimental
511
- // */
512
- // status = $command({
513
- // name: "db:status",
514
- // description: "Show pending database migrations status",
515
- // summary: false,
516
- // args: t.optional(
517
- // t.text({
518
- // title: "path",
519
- // description: "Path to the Alepha server entry file",
520
- // }),
521
- // ),
522
- // flags: drizzleCommandFlags,
523
- // handler: async ({ flags }) => {
524
- // // TODO: Implement db:status
525
- // this.log.warn("db:status is not yet implemented");
526
- // if (flags.provider) {
527
- // this.log.info(`Provider filter: ${flags.provider}`);
528
- // }
529
- // },
530
- // });
531
444
  }