alepha 0.13.6 → 0.13.7
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.
- package/dist/api-audits/index.browser.js +116 -0
- package/dist/api-audits/index.browser.js.map +1 -0
- package/dist/api-audits/index.d.ts +1194 -0
- package/dist/api-audits/index.js +674 -0
- package/dist/api-audits/index.js.map +1 -0
- package/dist/api-notifications/index.d.ts +147 -147
- package/dist/api-parameters/index.browser.js +36 -5
- package/dist/api-parameters/index.browser.js.map +1 -1
- package/dist/api-parameters/index.d.ts +711 -33
- package/dist/api-parameters/index.js +831 -17
- package/dist/api-parameters/index.js.map +1 -1
- package/dist/api-users/index.d.ts +793 -780
- package/dist/api-users/index.js +699 -19
- package/dist/api-users/index.js.map +1 -1
- package/dist/api-verifications/index.js +2 -1
- package/dist/api-verifications/index.js.map +1 -1
- package/dist/bin/index.js +1 -0
- package/dist/bin/index.js.map +1 -1
- package/dist/cli/index.d.ts +85 -31
- package/dist/cli/index.js +205 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +67 -6
- package/dist/command/index.js +30 -3
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +241 -61
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +170 -90
- package/dist/core/index.js +264 -67
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +248 -65
- package/dist/core/index.native.js.map +1 -1
- package/dist/email/index.js +15 -10554
- package/dist/email/index.js.map +1 -1
- package/dist/logger/index.d.ts +4 -4
- package/dist/logger/index.js +77 -72
- package/dist/logger/index.js.map +1 -1
- package/dist/orm/index.d.ts +5 -1
- package/dist/orm/index.js +24 -7
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/index.d.ts +4 -4
- package/dist/scheduler/index.d.ts +6 -6
- package/dist/server/index.d.ts +10 -1
- package/dist/server/index.js +20 -6
- package/dist/server/index.js.map +1 -1
- package/dist/server-auth/index.d.ts +163 -152
- package/dist/server-auth/index.js +40 -10
- package/dist/server-auth/index.js.map +1 -1
- package/dist/server-cookies/index.js +5 -1
- package/dist/server-cookies/index.js.map +1 -1
- package/dist/server-links/index.d.ts +33 -33
- package/dist/server-security/index.d.ts +9 -9
- package/dist/thread/index.js +2 -2
- package/dist/thread/index.js.map +1 -1
- package/dist/vite/index.d.ts +2 -2
- package/dist/vite/index.js +102 -45
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js +3 -3
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.js +4 -4
- package/dist/websocket/index.js.map +1 -1
- package/package.json +14 -9
- package/src/api-audits/controllers/AuditController.ts +186 -0
- package/src/api-audits/entities/audits.ts +132 -0
- package/src/api-audits/index.browser.ts +18 -0
- package/src/api-audits/index.ts +58 -0
- package/src/api-audits/primitives/$audit.ts +159 -0
- package/src/api-audits/schemas/auditQuerySchema.ts +23 -0
- package/src/api-audits/schemas/auditResourceSchema.ts +9 -0
- package/src/api-audits/schemas/createAuditSchema.ts +27 -0
- package/src/api-audits/services/AuditService.ts +412 -0
- package/src/api-parameters/controllers/ConfigController.ts +324 -0
- package/src/api-parameters/entities/parameters.ts +93 -10
- package/src/api-parameters/index.ts +43 -4
- package/src/api-parameters/primitives/$config.ts +291 -19
- package/src/api-parameters/schedulers/ConfigActivationScheduler.ts +30 -0
- package/src/api-parameters/services/ConfigStore.ts +491 -0
- package/src/api-users/atoms/realmAuthSettingsAtom.ts +19 -0
- package/src/api-users/controllers/UserRealmController.ts +0 -2
- package/src/api-users/index.ts +2 -0
- package/src/api-users/primitives/$userRealm.ts +18 -3
- package/src/api-users/providers/UserRealmProvider.ts +6 -3
- package/src/api-users/services/RegistrationService.ts +2 -1
- package/src/api-users/services/SessionService.ts +4 -0
- package/src/api-users/services/UserService.ts +3 -0
- package/src/api-verifications/index.ts +7 -1
- package/src/bin/index.ts +1 -0
- package/src/cli/assets/biomeJson.ts +1 -1
- package/src/cli/assets/dummySpecTs.ts +7 -0
- package/src/cli/assets/editorconfig.ts +13 -0
- package/src/cli/assets/mainTs.ts +14 -0
- package/src/cli/commands/BiomeCommands.ts +2 -0
- package/src/cli/commands/CoreCommands.ts +28 -9
- package/src/cli/commands/VerifyCommands.ts +2 -1
- package/src/cli/commands/ViteCommands.ts +8 -9
- package/src/cli/services/AlephaCliUtils.ts +214 -23
- package/src/command/helpers/Asker.ts +0 -1
- package/src/command/primitives/$command.ts +67 -0
- package/src/command/providers/CliProvider.ts +39 -8
- package/src/core/Alepha.ts +40 -30
- package/src/core/helpers/jsonSchemaToTypeBox.ts +307 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +30 -3
- package/src/core/providers/EventManager.ts +1 -1
- package/src/core/providers/StateManager.ts +23 -12
- package/src/core/providers/TypeProvider.ts +26 -34
- package/src/logger/index.ts +8 -6
- package/src/logger/primitives/$logger.ts +1 -1
- package/src/logger/providers/{SimpleFormatterProvider.ts → PrettyFormatterProvider.ts} +10 -1
- package/src/orm/index.ts +6 -0
- package/src/orm/services/PgRelationManager.ts +2 -2
- package/src/orm/services/PostgresModelBuilder.ts +11 -7
- package/src/orm/services/Repository.ts +16 -7
- package/src/orm/services/SqliteModelBuilder.ts +10 -0
- package/src/server/index.ts +6 -0
- package/src/server/primitives/$action.ts +10 -1
- package/src/server/providers/ServerBodyParserProvider.ts +11 -5
- package/src/server/providers/ServerRouterProvider.ts +13 -7
- package/src/server-auth/primitives/$auth.ts +7 -0
- package/src/server-auth/providers/ServerAuthProvider.ts +51 -8
- package/src/server-cookies/index.ts +2 -1
- package/src/thread/primitives/$thread.ts +2 -2
- package/src/vite/index.ts +0 -2
- package/src/vite/tasks/buildServer.ts +3 -4
- package/src/vite/tasks/generateCloudflare.ts +35 -19
- package/src/vite/tasks/generateDocker.ts +18 -4
- package/src/vite/tasks/generateSitemap.ts +5 -7
- package/src/vite/tasks/generateVercel.ts +76 -41
- package/src/vite/tasks/runAlepha.ts +16 -1
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +3 -11
- package/src/websocket/services/WebSocketClient.ts +3 -3
- package/dist/cli/dist-BlfFtOk2.js +0 -2770
- package/dist/cli/dist-BlfFtOk2.js.map +0 -1
- package/src/api-parameters/controllers/ParameterController.ts +0 -45
- package/src/api-parameters/services/ParameterStore.ts +0 -23
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
2
|
import { VerificationController } from "./controllers/VerificationController.ts";
|
|
3
3
|
import { VerificationJobs } from "./jobs/VerificationJobs.ts";
|
|
4
|
+
import { VerificationParameters } from "./parameters/VerificationParameters.ts";
|
|
4
5
|
import { VerificationService } from "./services/VerificationService.ts";
|
|
5
6
|
|
|
6
7
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -25,5 +26,10 @@ export * from "./services/VerificationService.ts";
|
|
|
25
26
|
*/
|
|
26
27
|
export const AlephaApiVerification = $module({
|
|
27
28
|
name: "alepha.api.verifications",
|
|
28
|
-
services: [
|
|
29
|
+
services: [
|
|
30
|
+
VerificationController,
|
|
31
|
+
VerificationJobs,
|
|
32
|
+
VerificationService,
|
|
33
|
+
VerificationParameters,
|
|
34
|
+
],
|
|
29
35
|
});
|
package/src/bin/index.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const mainTs = () => `
|
|
2
|
+
import { Alepha, run } from "alepha";
|
|
3
|
+
import { $logger } from "alepha/logger";
|
|
4
|
+
|
|
5
|
+
const alepha = Alepha.create();
|
|
6
|
+
|
|
7
|
+
alepha.with(() => {
|
|
8
|
+
const log = $logger();
|
|
9
|
+
|
|
10
|
+
log.info("Hello from Alepha!");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
run(alepha);
|
|
14
|
+
`.trim();
|
|
@@ -12,6 +12,7 @@ export class BiomeCommands {
|
|
|
12
12
|
description: "Format the codebase using Biome",
|
|
13
13
|
handler: async ({ root }) => {
|
|
14
14
|
await this.utils.ensureConfig(root, { biomeJson: true });
|
|
15
|
+
await this.utils.ensureDependency(root, "@biomejs/biome");
|
|
15
16
|
await this.utils.exec(`biome format --fix`);
|
|
16
17
|
},
|
|
17
18
|
});
|
|
@@ -21,6 +22,7 @@ export class BiomeCommands {
|
|
|
21
22
|
description: "Run linter across the codebase using Biome",
|
|
22
23
|
handler: async ({ root }) => {
|
|
23
24
|
await this.utils.ensureConfig(root, { biomeJson: true });
|
|
25
|
+
await this.utils.ensureDependency(root, "@biomejs/biome");
|
|
24
26
|
await this.utils.exec(`biome check --formatter-enabled=false --fix`);
|
|
25
27
|
},
|
|
26
28
|
});
|
|
@@ -58,6 +58,8 @@ export class CoreCommands {
|
|
|
58
58
|
// choose package manager
|
|
59
59
|
yarn: t.optional(t.boolean({ description: "Use Yarn package manager" })),
|
|
60
60
|
pnpm: t.optional(t.boolean({ description: "Use pnpm package manager" })),
|
|
61
|
+
npm: t.optional(t.boolean({ description: "Use npm package manager" })),
|
|
62
|
+
bun: t.optional(t.boolean({ description: "Use Bun package manager" })),
|
|
61
63
|
// choose which dependencies to add
|
|
62
64
|
react: t.optional(
|
|
63
65
|
t.boolean({ description: "Include Alepha React dependencies" }),
|
|
@@ -65,6 +67,9 @@ export class CoreCommands {
|
|
|
65
67
|
ui: t.optional(
|
|
66
68
|
t.boolean({ description: "Include Alepha UI dependencies" }),
|
|
67
69
|
),
|
|
70
|
+
test: t.optional(
|
|
71
|
+
t.boolean({ description: "Include Vitest and create test directory" }),
|
|
72
|
+
),
|
|
68
73
|
}),
|
|
69
74
|
handler: async ({ run, flags, root }) => {
|
|
70
75
|
if (flags.ui) {
|
|
@@ -72,31 +77,45 @@ export class CoreCommands {
|
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
await run({
|
|
75
|
-
name: "
|
|
80
|
+
name: "ensuring configuration files",
|
|
76
81
|
handler: async () => {
|
|
77
82
|
await this.utils.ensureConfig(root, {
|
|
78
83
|
tsconfigJson: true,
|
|
79
84
|
packageJson: flags,
|
|
80
85
|
biomeJson: true,
|
|
81
86
|
viteConfigTs: true,
|
|
87
|
+
editorconfig: true,
|
|
82
88
|
indexHtml: !!flags.react,
|
|
83
89
|
});
|
|
90
|
+
|
|
91
|
+
// Create src/main.ts if src directory is empty or doesn't exist
|
|
92
|
+
if (!flags.react) {
|
|
93
|
+
await this.utils.ensureSrcMain(root);
|
|
94
|
+
}
|
|
84
95
|
},
|
|
85
96
|
});
|
|
86
97
|
|
|
87
98
|
// TODO: check if all alepha dependencies are same version
|
|
88
99
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
if (flags.yarn || guessedPm === "yarn") {
|
|
100
|
+
const pm = await this.utils.getPackageManager(root, flags);
|
|
101
|
+
if (pm === "yarn") {
|
|
92
102
|
await this.utils.ensureYarn(root);
|
|
93
103
|
await run("yarn set version stable");
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
});
|
|
104
|
+
} else if (pm === "pnpm") {
|
|
105
|
+
await this.utils.ensurePnpm(root);
|
|
97
106
|
} else {
|
|
98
|
-
await
|
|
99
|
-
|
|
107
|
+
await this.utils.ensureNpm(root);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await run(`${pm} install`, {
|
|
111
|
+
alias: `installing dependencies with ${pm}`,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Install vitest and create test directory if --test flag is set
|
|
115
|
+
if (flags.test) {
|
|
116
|
+
await this.utils.ensureTestDir(root);
|
|
117
|
+
await run(`${pm} ${pm === "yarn" ? "add" : "install"} -D vitest`, {
|
|
118
|
+
alias: "setup testing with Vitest",
|
|
100
119
|
});
|
|
101
120
|
}
|
|
102
121
|
},
|
|
@@ -48,7 +48,8 @@ export class VerifyCommands {
|
|
|
48
48
|
public readonly typecheck = $command({
|
|
49
49
|
name: "typecheck",
|
|
50
50
|
description: "Check TypeScript types across the codebase",
|
|
51
|
-
handler: async () => {
|
|
51
|
+
handler: async ({ root }) => {
|
|
52
|
+
await this.utils.ensureDependency(root, "typescript");
|
|
52
53
|
await this.utils.exec("tsc --noEmit");
|
|
53
54
|
},
|
|
54
55
|
});
|
|
@@ -75,6 +75,8 @@ export class ViteCommands {
|
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// Ensure vite is installed before running
|
|
79
|
+
await this.utils.ensureDependency(root, "vite");
|
|
78
80
|
await this.utils.exec(`vite`);
|
|
79
81
|
},
|
|
80
82
|
});
|
|
@@ -132,6 +134,10 @@ export class ViteCommands {
|
|
|
132
134
|
const distDir = "dist";
|
|
133
135
|
const clientDir = "public";
|
|
134
136
|
|
|
137
|
+
await this.utils.ensureDependency(root, "vite", {
|
|
138
|
+
run,
|
|
139
|
+
});
|
|
140
|
+
|
|
135
141
|
await run.rm("dist", {
|
|
136
142
|
alias: "clean dist",
|
|
137
143
|
});
|
|
@@ -301,15 +307,8 @@ export class ViteCommands {
|
|
|
301
307
|
viteConfigTs: true,
|
|
302
308
|
});
|
|
303
309
|
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
await import("vitest");
|
|
307
|
-
} catch {
|
|
308
|
-
this.log.error(
|
|
309
|
-
"Vitest is not installed. Please install it with `npm install -D vitest` or `yarn add -D vitest`.",
|
|
310
|
-
);
|
|
311
|
-
process.exit(1);
|
|
312
|
-
}
|
|
310
|
+
// Ensure vitest is installed before running
|
|
311
|
+
await this.utils.ensureDependency(root, "vitest");
|
|
313
312
|
|
|
314
313
|
await this.utils.exec(`vitest run ${this.env.VITEST_ARGS}`);
|
|
315
314
|
},
|
|
@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { $inject, Alepha, AlephaError } from "alepha";
|
|
5
|
+
import type { RunnerMethod } from "alepha/command";
|
|
5
6
|
import { FileSystemProvider } from "alepha/file";
|
|
6
7
|
import { $logger } from "alepha/logger";
|
|
7
8
|
import type { DrizzleKitProvider, RepositoryProvider } from "alepha/orm";
|
|
@@ -9,8 +10,11 @@ import { boot } from "alepha/vite";
|
|
|
9
10
|
import { tsImport } from "tsx/esm/api";
|
|
10
11
|
import { appRouterTs } from "../assets/appRouterTs.ts";
|
|
11
12
|
import { biomeJson } from "../assets/biomeJson.ts";
|
|
13
|
+
import { dummySpecTs } from "../assets/dummySpecTs.ts";
|
|
14
|
+
import { editorconfig } from "../assets/editorconfig.ts";
|
|
12
15
|
import { indexHtml } from "../assets/indexHtml.ts";
|
|
13
16
|
import { mainBrowserTs } from "../assets/mainBrowserTs.ts";
|
|
17
|
+
import { mainTs } from "../assets/mainTs.ts";
|
|
14
18
|
import { tsconfigJson } from "../assets/tsconfigJson.ts";
|
|
15
19
|
import { viteConfigTs } from "../assets/viteConfigTs.ts";
|
|
16
20
|
import { version } from "../version.ts";
|
|
@@ -32,10 +36,6 @@ export class AlephaCliUtils {
|
|
|
32
36
|
/**
|
|
33
37
|
* Execute a command using npx with inherited stdio.
|
|
34
38
|
*
|
|
35
|
-
* @param command - The command to execute (will be passed to npx)
|
|
36
|
-
* @param env - Optional environment variables to set for the command
|
|
37
|
-
* @returns Promise that resolves when the process exits
|
|
38
|
-
*
|
|
39
39
|
* @example
|
|
40
40
|
* ```ts
|
|
41
41
|
* const runner = alepha.inject(ProcessRunner);
|
|
@@ -44,40 +44,63 @@ export class AlephaCliUtils {
|
|
|
44
44
|
*/
|
|
45
45
|
public async exec(
|
|
46
46
|
command: string,
|
|
47
|
-
|
|
47
|
+
options: {
|
|
48
|
+
env?: Record<string, string>;
|
|
49
|
+
global?: boolean;
|
|
50
|
+
} = {},
|
|
48
51
|
): Promise<void> {
|
|
49
52
|
const root = process.cwd();
|
|
50
53
|
this.log.debug(`Executing command: ${command}`, { cwd: root });
|
|
51
54
|
|
|
55
|
+
const runExec = async (app: string, args: string[]) => {
|
|
56
|
+
const prog = spawn(app, args, {
|
|
57
|
+
stdio: "inherit",
|
|
58
|
+
cwd: root,
|
|
59
|
+
env: {
|
|
60
|
+
...process.env,
|
|
61
|
+
...options.env,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await new Promise<void>((resolve) =>
|
|
66
|
+
prog.on("exit", () => {
|
|
67
|
+
resolve();
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (options.global) {
|
|
73
|
+
const [app, ...args] = command.split(" ");
|
|
74
|
+
await runExec(app, args);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
52
78
|
const suffix = process.platform === "win32" ? ".cmd" : "";
|
|
53
79
|
const [app, ...args] = command.split(" ");
|
|
54
|
-
|
|
80
|
+
|
|
81
|
+
// find executable inside project node_modules
|
|
82
|
+
let execPath = await this.checkFileExists(
|
|
55
83
|
root,
|
|
56
84
|
`node_modules/.bin/${app}${suffix}`,
|
|
57
85
|
true,
|
|
58
86
|
);
|
|
59
87
|
|
|
88
|
+
// or, find executable inside alepha package node_modules (pnpm style)
|
|
89
|
+
if (!execPath) {
|
|
90
|
+
execPath = await this.checkFileExists(
|
|
91
|
+
root,
|
|
92
|
+
`node_modules/alepha/node_modules/.bin/${app}${suffix}`,
|
|
93
|
+
true,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
60
97
|
if (!execPath) {
|
|
61
98
|
throw new AlephaError(
|
|
62
99
|
`Could not find executable for command '${app}'. Make sure the package is installed.`,
|
|
63
100
|
);
|
|
64
101
|
}
|
|
65
102
|
|
|
66
|
-
|
|
67
|
-
stdio: "inherit",
|
|
68
|
-
cwd: root,
|
|
69
|
-
env: {
|
|
70
|
-
...process.env,
|
|
71
|
-
...env,
|
|
72
|
-
// NODE_OPTIONS: "--import tsx",
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
await new Promise<void>((resolve) =>
|
|
77
|
-
prog.on("exit", () => {
|
|
78
|
-
resolve();
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
103
|
+
await runExec(execPath, args);
|
|
81
104
|
}
|
|
82
105
|
|
|
83
106
|
/**
|
|
@@ -139,6 +162,22 @@ export class AlephaCliUtils {
|
|
|
139
162
|
await this.fs.rm(join(root, "pnpm-lock.yaml"), { force: true });
|
|
140
163
|
}
|
|
141
164
|
|
|
165
|
+
public async ensurePnpm(root: string): Promise<void> {
|
|
166
|
+
// remove lock files from other package managers
|
|
167
|
+
await this.fs.rm(join(root, "package-lock.json"), { force: true });
|
|
168
|
+
await this.fs.rm(join(root, "yarn.lock"), { force: true });
|
|
169
|
+
await this.fs.rm(join(root, ".yarn"), { force: true, recursive: true });
|
|
170
|
+
await this.fs.rm(join(root, ".yarnrc.yml"), { force: true });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public async ensureNpm(root: string): Promise<void> {
|
|
174
|
+
// remove lock files from other package managers
|
|
175
|
+
await this.fs.rm(join(root, "pnpm-lock.yaml"), { force: true });
|
|
176
|
+
await this.fs.rm(join(root, "yarn.lock"), { force: true });
|
|
177
|
+
await this.fs.rm(join(root, ".yarn"), { force: true, recursive: true });
|
|
178
|
+
await this.fs.rm(join(root, ".yarnrc.yml"), { force: true });
|
|
179
|
+
}
|
|
180
|
+
|
|
142
181
|
/**
|
|
143
182
|
* Generate package.json content with Alepha dependencies.
|
|
144
183
|
*
|
|
@@ -232,6 +271,7 @@ export class AlephaCliUtils {
|
|
|
232
271
|
viteConfigTs?: boolean;
|
|
233
272
|
indexHtml?: boolean;
|
|
234
273
|
biomeJson?: boolean;
|
|
274
|
+
editorconfig?: boolean;
|
|
235
275
|
},
|
|
236
276
|
) {
|
|
237
277
|
const tasks: Promise<void>[] = [];
|
|
@@ -256,6 +296,9 @@ export class AlephaCliUtils {
|
|
|
256
296
|
if (opts.biomeJson) {
|
|
257
297
|
tasks.push(this.ensureBiomeConfig(root));
|
|
258
298
|
}
|
|
299
|
+
if (opts.editorconfig) {
|
|
300
|
+
tasks.push(this.ensureEditorConfig(root));
|
|
301
|
+
}
|
|
259
302
|
|
|
260
303
|
await Promise.all(tasks);
|
|
261
304
|
}
|
|
@@ -353,6 +396,17 @@ export class AlephaCliUtils {
|
|
|
353
396
|
await this.ensureFileExists(root, "biome.json", biomeJson, true);
|
|
354
397
|
}
|
|
355
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Ensure .editorconfig exists in the project.
|
|
401
|
+
*
|
|
402
|
+
* Creates a standard .editorconfig if none exists.
|
|
403
|
+
*
|
|
404
|
+
* @param root - The root directory of the project
|
|
405
|
+
*/
|
|
406
|
+
public async ensureEditorConfig(root: string): Promise<void> {
|
|
407
|
+
await this.ensureFileExists(root, ".editorconfig", editorconfig, true);
|
|
408
|
+
}
|
|
409
|
+
|
|
356
410
|
// ===================================================================================================================
|
|
357
411
|
// Drizzle ORM & Kit Utilities
|
|
358
412
|
// ===================================================================================================================
|
|
@@ -585,7 +639,9 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
|
|
|
585
639
|
await this.exec(
|
|
586
640
|
`drizzle-kit ${options.command} --config=${drizzleConfigJsPath}${flags}`,
|
|
587
641
|
{
|
|
588
|
-
|
|
642
|
+
env: {
|
|
643
|
+
NODE_OPTIONS: "--import tsx",
|
|
644
|
+
},
|
|
589
645
|
},
|
|
590
646
|
);
|
|
591
647
|
}
|
|
@@ -593,7 +649,20 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
|
|
|
593
649
|
|
|
594
650
|
public async getPackageManager(
|
|
595
651
|
root: string,
|
|
596
|
-
|
|
652
|
+
flags?: { yarn?: boolean; pnpm?: boolean; npm?: boolean; bun?: boolean },
|
|
653
|
+
): Promise<"yarn" | "pnpm" | "npm" | "bun"> {
|
|
654
|
+
if (flags?.yarn) {
|
|
655
|
+
return "yarn";
|
|
656
|
+
}
|
|
657
|
+
if (flags?.pnpm) {
|
|
658
|
+
return "pnpm";
|
|
659
|
+
}
|
|
660
|
+
if (flags?.npm) {
|
|
661
|
+
return "npm";
|
|
662
|
+
}
|
|
663
|
+
if (flags?.bun) {
|
|
664
|
+
return "bun";
|
|
665
|
+
}
|
|
597
666
|
if (await this.checkFileExists(root, "yarn.lock", true)) {
|
|
598
667
|
return "yarn";
|
|
599
668
|
}
|
|
@@ -635,6 +704,64 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
|
|
|
635
704
|
return this.fs.exists(join(root, dirName));
|
|
636
705
|
}
|
|
637
706
|
|
|
707
|
+
/**
|
|
708
|
+
* Ensure src/main.ts exists with a minimal Alepha bootstrap.
|
|
709
|
+
*
|
|
710
|
+
* Creates the src directory and main.ts file if the src directory
|
|
711
|
+
* doesn't exist or is empty.
|
|
712
|
+
*
|
|
713
|
+
* @param root - The root directory of the project
|
|
714
|
+
*/
|
|
715
|
+
public async ensureSrcMain(root: string): Promise<void> {
|
|
716
|
+
const srcDir = join(root, "src");
|
|
717
|
+
const mainPath = join(srcDir, "main.ts");
|
|
718
|
+
|
|
719
|
+
// Check if src directory exists
|
|
720
|
+
const srcExists = await this.fs.exists(srcDir);
|
|
721
|
+
|
|
722
|
+
if (!srcExists) {
|
|
723
|
+
// Create src directory and main.ts
|
|
724
|
+
await this.fs.mkdir(srcDir, { recursive: true });
|
|
725
|
+
await this.fs.writeFile(mainPath, mainTs());
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Check if src directory is empty
|
|
730
|
+
const files = await this.fs.ls(srcDir);
|
|
731
|
+
if (files.length === 0) {
|
|
732
|
+
await this.fs.writeFile(mainPath, mainTs());
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Ensure test directory exists with a dummy test file.
|
|
738
|
+
*
|
|
739
|
+
* Creates the test directory and a dummy.spec.ts file if the test directory
|
|
740
|
+
* doesn't exist or is empty.
|
|
741
|
+
*
|
|
742
|
+
* @param root - The root directory of the project
|
|
743
|
+
*/
|
|
744
|
+
public async ensureTestDir(root: string): Promise<void> {
|
|
745
|
+
const testDir = join(root, "test");
|
|
746
|
+
const dummyPath = join(testDir, "dummy.spec.ts");
|
|
747
|
+
|
|
748
|
+
// Check if test directory exists
|
|
749
|
+
const testExists = await this.fs.exists(testDir);
|
|
750
|
+
|
|
751
|
+
if (!testExists) {
|
|
752
|
+
// Create test directory and dummy.spec.ts
|
|
753
|
+
await this.fs.mkdir(testDir, { recursive: true });
|
|
754
|
+
await this.fs.writeFile(dummyPath, dummySpecTs());
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// Check if test directory is empty
|
|
759
|
+
const files = await this.fs.ls(testDir);
|
|
760
|
+
if (files.length === 0) {
|
|
761
|
+
await this.fs.writeFile(dummyPath, dummySpecTs());
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
638
765
|
async readPackageJson(root: string): Promise<Record<string, any>> {
|
|
639
766
|
const packageJson = await this.fs
|
|
640
767
|
.createFile({
|
|
@@ -643,6 +770,70 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
|
|
|
643
770
|
.text();
|
|
644
771
|
return JSON.parse(packageJson);
|
|
645
772
|
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Check if a dependency is installed in the project.
|
|
776
|
+
*
|
|
777
|
+
* @param root - The root directory of the project
|
|
778
|
+
* @param packageName - The name of the package to check
|
|
779
|
+
* @returns True if the package is in dependencies or devDependencies
|
|
780
|
+
*/
|
|
781
|
+
async hasDependency(root: string, packageName: string): Promise<boolean> {
|
|
782
|
+
try {
|
|
783
|
+
const pkg = await this.readPackageJson(root);
|
|
784
|
+
return !!(
|
|
785
|
+
pkg.dependencies?.[packageName] || pkg.devDependencies?.[packageName]
|
|
786
|
+
);
|
|
787
|
+
} catch {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Install a dependency if it's missing from the project.
|
|
794
|
+
*
|
|
795
|
+
* Automatically detects the package manager (yarn, pnpm, npm) and installs
|
|
796
|
+
* the package as a dev dependency if not already present.
|
|
797
|
+
*/
|
|
798
|
+
async ensureDependency(
|
|
799
|
+
root: string,
|
|
800
|
+
packageName: string,
|
|
801
|
+
options: { dev?: boolean; run?: RunnerMethod } = {},
|
|
802
|
+
): Promise<void> {
|
|
803
|
+
const { dev = true } = options;
|
|
804
|
+
|
|
805
|
+
if (await this.hasDependency(root, packageName)) {
|
|
806
|
+
this.log.debug(`Dependency '${packageName}' is already installed`);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const pm = await this.getPackageManager(root);
|
|
811
|
+
let cmd: string;
|
|
812
|
+
|
|
813
|
+
switch (pm) {
|
|
814
|
+
case "yarn":
|
|
815
|
+
cmd = `yarn add ${dev ? "-D" : ""} ${packageName}`;
|
|
816
|
+
break;
|
|
817
|
+
case "pnpm":
|
|
818
|
+
cmd = `pnpm add ${dev ? "-D" : ""} ${packageName}`;
|
|
819
|
+
break;
|
|
820
|
+
default:
|
|
821
|
+
cmd = `npm install ${dev ? "--save-dev" : ""} ${packageName}`;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
cmd = cmd.replace(/\s+/g, " ").trim();
|
|
825
|
+
|
|
826
|
+
if (options.run) {
|
|
827
|
+
// if it's during a Runner flow, just use the runner's run method
|
|
828
|
+
await options.run(cmd, {
|
|
829
|
+
alias: `installing ${packageName}`,
|
|
830
|
+
});
|
|
831
|
+
} else {
|
|
832
|
+
// else, run directly with our util exec method
|
|
833
|
+
this.log.debug(`Installing ${packageName}`);
|
|
834
|
+
await this.exec(cmd, { global: true });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
646
837
|
}
|
|
647
838
|
|
|
648
839
|
export interface DependencyModes {
|
|
@@ -82,6 +82,61 @@ export interface CommandPrimitiveOptions<T extends TObject, A extends TSchema> {
|
|
|
82
82
|
* Equivalent to setting name to an empty string "".
|
|
83
83
|
*/
|
|
84
84
|
root?: boolean;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Run this command's handler BEFORE the specified target command.
|
|
88
|
+
*
|
|
89
|
+
* Pre-hooks are not listed in help and cannot be called directly.
|
|
90
|
+
* They receive the same parsed flags and args as the target command.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* class BuildCommands {
|
|
95
|
+
* prebuild = $command({
|
|
96
|
+
* pre: "build",
|
|
97
|
+
* handler: async ({ run }) => {
|
|
98
|
+
* await run("cleaning dist folder...", () => fs.rm("dist"));
|
|
99
|
+
* }
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* build = $command({
|
|
103
|
+
* name: "build",
|
|
104
|
+
* handler: async () => { ... }
|
|
105
|
+
* });
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
pre?: string;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Run this command's handler AFTER the specified target command.
|
|
113
|
+
*
|
|
114
|
+
* Post-hooks are not listed in help and cannot be called directly.
|
|
115
|
+
* They receive the same parsed flags and args as the target command.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* class BuildCommands {
|
|
120
|
+
* build = $command({
|
|
121
|
+
* name: "build",
|
|
122
|
+
* handler: async () => { ... }
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* postbuild = $command({
|
|
126
|
+
* post: "build",
|
|
127
|
+
* handler: async ({ run }) => {
|
|
128
|
+
* await run("generating checksums...", generateChecksums);
|
|
129
|
+
* }
|
|
130
|
+
* });
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
post?: string;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* If true, this command will be hidden from the help output.
|
|
138
|
+
*/
|
|
139
|
+
hide?: boolean;
|
|
85
140
|
}
|
|
86
141
|
|
|
87
142
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -93,10 +148,22 @@ export class CommandPrimitive<
|
|
|
93
148
|
public readonly flags = this.options.flags ?? t.object({});
|
|
94
149
|
public readonly aliases = this.options.aliases ?? [];
|
|
95
150
|
|
|
151
|
+
protected onInit() {
|
|
152
|
+
if (this.options.pre || this.options.post) {
|
|
153
|
+
this.options.hide ??= true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
96
157
|
public get name(): string {
|
|
97
158
|
if (this.options.root) {
|
|
98
159
|
return "";
|
|
99
160
|
}
|
|
161
|
+
if (this.options.pre) {
|
|
162
|
+
return `pre${this.options.pre}`;
|
|
163
|
+
}
|
|
164
|
+
if (this.options.post) {
|
|
165
|
+
return `post${this.options.post}`;
|
|
166
|
+
}
|
|
100
167
|
return this.options.name ?? `${this.config.propertyKey}`;
|
|
101
168
|
}
|
|
102
169
|
}
|