alepha 0.14.4 → 0.15.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.
- package/README.md +1 -4
- package/dist/api/audits/index.d.ts +619 -731
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.d.ts +185 -298
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +0 -1
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +245 -356
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/notifications/index.d.ts +238 -350
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/parameters/index.d.ts +499 -611
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/users/index.browser.js +1 -2
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +1697 -1804
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +178 -151
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +132 -132
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/batch/index.d.ts +122 -122
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +1 -2
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +163 -163
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/cache/core/index.d.ts +46 -46
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cli/index.d.ts +302 -299
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +966 -564
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +303 -299
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +11 -7
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +419 -99
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +718 -625
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +420 -99
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +419 -99
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +44 -44
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +4 -4
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +97 -50
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +129 -33
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +7981 -14
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/file/index.d.ts +523 -390
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +253 -1
- package/dist/file/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +208 -208
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/logger/index.d.ts +25 -26
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/mcp/index.d.ts +197 -197
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/orm/chunk-DtkW-qnP.js +38 -0
- package/dist/orm/index.browser.js.map +1 -1
- package/dist/orm/index.bun.js +2814 -0
- package/dist/orm/index.bun.js.map +1 -0
- package/dist/orm/index.d.ts +1205 -1057
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +2056 -1753
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +248 -248
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/redis/index.bun.js +285 -0
- package/dist/redis/index.bun.js.map +1 -0
- package/dist/redis/index.d.ts +118 -136
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +18 -38
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +69 -69
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/router/index.d.ts +6 -6
- package/dist/router/index.d.ts.map +1 -1
- package/dist/scheduler/index.d.ts +25 -25
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/security/index.browser.js +5 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +417 -254
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +386 -86
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +277 -277
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +20 -20
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +60 -57
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +1 -1
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +3 -3
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/cookies/index.d.ts +6 -6
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +3 -3
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +242 -150
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +288 -122
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +11 -12
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/health/index.d.ts +0 -1
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/helmet/index.d.ts +2 -2
- package/dist/server/helmet/index.d.ts.map +1 -1
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +84 -85
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +1 -2
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/multipart/index.d.ts +6 -6
- package/dist/server/multipart/index.d.ts.map +1 -1
- package/dist/server/proxy/index.d.ts +102 -103
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.d.ts +16 -16
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/static/index.d.ts +44 -44
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/swagger/index.d.ts +48 -49
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +1 -2
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +13 -11
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +7 -7
- package/dist/sms/index.js.map +1 -1
- package/dist/thread/index.d.ts +71 -72
- package/dist/thread/index.d.ts.map +1 -1
- package/dist/topic/core/index.d.ts +318 -318
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/redis/index.d.ts +6 -6
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/vite/index.d.ts +5720 -159
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +41 -18
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.browser.js +6 -6
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +247 -247
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +6 -6
- package/dist/websocket/index.js.map +1 -1
- package/package.json +9 -14
- package/src/api/files/controllers/AdminFileStatsController.ts +0 -1
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +5 -0
- package/src/api/users/controllers/{UserRealmController.ts → RealmController.ts} +11 -11
- package/src/api/users/entities/users.ts +1 -1
- package/src/api/users/index.ts +8 -8
- package/src/api/users/primitives/{$userRealm.ts → $realm.ts} +17 -19
- package/src/api/users/providers/{UserRealmProvider.ts → RealmProvider.ts} +26 -30
- package/src/api/users/schemas/{userRealmConfigSchema.ts → realmConfigSchema.ts} +2 -2
- package/src/api/users/services/CredentialService.ts +7 -7
- package/src/api/users/services/IdentityService.ts +4 -4
- package/src/api/users/services/RegistrationService.spec.ts +25 -27
- package/src/api/users/services/RegistrationService.ts +38 -27
- package/src/api/users/services/SessionCrudService.ts +3 -3
- package/src/api/users/services/SessionService.spec.ts +3 -3
- package/src/api/users/services/SessionService.ts +28 -9
- package/src/api/users/services/UserService.ts +7 -7
- package/src/batch/providers/BatchProvider.ts +1 -2
- package/src/cli/apps/AlephaPackageBuilderCli.ts +38 -19
- package/src/cli/assets/apiHelloControllerTs.ts +18 -0
- package/src/cli/assets/apiIndexTs.ts +16 -0
- package/src/cli/assets/claudeMd.ts +303 -0
- package/src/cli/assets/mainBrowserTs.ts +2 -2
- package/src/cli/assets/mainServerTs.ts +24 -0
- package/src/cli/assets/webAppRouterTs.ts +15 -0
- package/src/cli/assets/webHelloComponentTsx.ts +16 -0
- package/src/cli/assets/webIndexTs.ts +16 -0
- package/src/cli/commands/build.ts +41 -21
- package/src/cli/commands/db.ts +21 -18
- package/src/cli/commands/deploy.ts +17 -5
- package/src/cli/commands/dev.ts +13 -17
- package/src/cli/commands/format.ts +8 -2
- package/src/cli/commands/init.ts +74 -29
- package/src/cli/commands/lint.ts +8 -2
- package/src/cli/commands/test.ts +8 -2
- package/src/cli/commands/typecheck.ts +5 -1
- package/src/cli/commands/verify.ts +4 -2
- package/src/cli/services/AlephaCliUtils.ts +39 -600
- package/src/cli/services/PackageManagerUtils.ts +301 -0
- package/src/cli/services/ProjectScaffolder.ts +306 -0
- package/src/command/helpers/Runner.ts +15 -3
- package/src/core/__tests__/Alepha-graph.spec.ts +4 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/index.ts +2 -0
- package/src/core/primitives/$hook.ts +6 -2
- package/src/core/primitives/$module.spec.ts +4 -0
- package/src/core/providers/AlsProvider.ts +1 -1
- package/src/core/providers/CodecManager.spec.ts +12 -6
- package/src/core/providers/CodecManager.ts +26 -6
- package/src/core/providers/EventManager.ts +169 -13
- package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +621 -0
- package/src/core/providers/KeylessJsonSchemaCodec.ts +407 -0
- package/src/core/providers/StateManager.spec.ts +27 -16
- package/src/email/providers/LocalEmailProvider.spec.ts +111 -87
- package/src/email/providers/LocalEmailProvider.ts +52 -15
- package/src/email/providers/NodemailerEmailProvider.ts +167 -56
- package/src/file/errors/FileError.ts +7 -0
- package/src/file/index.ts +9 -1
- package/src/file/providers/MemoryFileSystemProvider.ts +393 -0
- package/src/orm/index.browser.ts +1 -19
- package/src/orm/index.bun.ts +77 -0
- package/src/orm/index.shared-server.ts +22 -0
- package/src/orm/index.shared.ts +15 -0
- package/src/orm/index.ts +19 -39
- package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -5
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +4 -0
- package/src/orm/providers/drivers/DatabaseProvider.ts +4 -0
- package/src/orm/providers/drivers/PglitePostgresProvider.ts +4 -0
- package/src/orm/services/Repository.ts +8 -0
- package/src/redis/index.bun.ts +35 -0
- package/src/redis/providers/BunRedisProvider.ts +12 -43
- package/src/redis/providers/BunRedisSubscriberProvider.ts +2 -3
- package/src/redis/providers/NodeRedisProvider.ts +16 -34
- package/src/{server/security → security}/__tests__/BasicAuth.spec.ts +11 -11
- package/src/{server/security → security}/__tests__/ServerSecurityProvider-realm.spec.ts +21 -16
- package/src/{server/security/providers → security/__tests__}/ServerSecurityProvider.spec.ts +5 -5
- package/src/security/index.browser.ts +5 -0
- package/src/security/index.ts +90 -7
- package/src/security/primitives/{$realm.spec.ts → $issuer.spec.ts} +11 -11
- package/src/security/primitives/{$realm.ts → $issuer.ts} +20 -17
- package/src/security/primitives/$role.ts +5 -5
- package/src/security/primitives/$serviceAccount.spec.ts +5 -5
- package/src/security/primitives/$serviceAccount.ts +3 -3
- package/src/{server/security → security}/providers/ServerSecurityProvider.ts +5 -7
- package/src/server/auth/primitives/$auth.ts +10 -10
- package/src/server/auth/primitives/$authCredentials.ts +3 -3
- package/src/server/auth/primitives/$authGithub.ts +3 -3
- package/src/server/auth/primitives/$authGoogle.ts +3 -3
- package/src/server/auth/providers/ServerAuthProvider.ts +13 -13
- package/src/server/cache/providers/ServerCacheProvider.ts +1 -1
- package/src/server/cookies/providers/ServerCookiesProvider.ts +3 -3
- package/src/server/core/providers/NodeHttpServerProvider.ts +25 -6
- package/src/server/core/providers/ServerBodyParserProvider.ts +19 -23
- package/src/server/core/providers/ServerLoggerProvider.ts +23 -19
- package/src/server/core/providers/ServerProvider.ts +144 -21
- package/src/server/core/providers/ServerRouterProvider.ts +259 -115
- package/src/server/core/providers/ServerTimingProvider.ts +2 -2
- package/src/server/links/index.ts +1 -1
- package/src/server/links/providers/LinkProvider.ts +1 -1
- package/src/server/swagger/index.ts +1 -1
- package/src/sms/providers/LocalSmsProvider.spec.ts +153 -111
- package/src/sms/providers/LocalSmsProvider.ts +8 -7
- package/src/vite/helpers/boot.ts +28 -17
- package/src/vite/tasks/buildServer.ts +12 -1
- package/src/vite/tasks/devServer.ts +3 -1
- package/src/vite/tasks/generateCloudflare.ts +7 -0
- package/dist/server/security/index.browser.js +0 -13
- package/dist/server/security/index.browser.js.map +0 -1
- package/dist/server/security/index.d.ts +0 -173
- package/dist/server/security/index.d.ts.map +0 -1
- package/dist/server/security/index.js +0 -311
- package/dist/server/security/index.js.map +0 -1
- package/src/cli/assets/appRouterTs.ts +0 -9
- package/src/cli/assets/mainTs.ts +0 -13
- package/src/server/security/index.browser.ts +0 -10
- package/src/server/security/index.ts +0 -94
- /package/src/{server/security → security}/primitives/$basicAuth.ts +0 -0
- /package/src/{server/security → security}/providers/ServerBasicAuthProvider.ts +0 -0
|
@@ -1,54 +1,40 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
2
|
import { $inject, Alepha, AlephaError } from "alepha";
|
|
5
|
-
import { EnvUtils
|
|
3
|
+
import { EnvUtils } from "alepha/command";
|
|
6
4
|
import { FileSystemProvider } from "alepha/file";
|
|
7
5
|
import { $logger } from "alepha/logger";
|
|
8
6
|
import { boot } from "alepha/vite";
|
|
9
|
-
import { appRouterTs } from "../assets/appRouterTs.ts";
|
|
10
|
-
import { biomeJson } from "../assets/biomeJson.ts";
|
|
11
|
-
import { dummySpecTs } from "../assets/dummySpecTs.ts";
|
|
12
|
-
import { editorconfig } from "../assets/editorconfig.ts";
|
|
13
|
-
import { indexHtml } from "../assets/indexHtml.ts";
|
|
14
|
-
import { mainBrowserTs } from "../assets/mainBrowserTs.ts";
|
|
15
|
-
import { mainTs } from "../assets/mainTs.ts";
|
|
16
|
-
import { tsconfigJson } from "../assets/tsconfigJson.ts";
|
|
17
|
-
import { version } from "../version.ts";
|
|
18
7
|
|
|
19
8
|
/**
|
|
20
|
-
*
|
|
9
|
+
* Core utility service for CLI commands.
|
|
21
10
|
*
|
|
22
|
-
*
|
|
23
|
-
* -
|
|
24
|
-
* -
|
|
25
|
-
* -
|
|
26
|
-
* -
|
|
27
|
-
* - Alepha instance loading
|
|
11
|
+
* Provides:
|
|
12
|
+
* - Command execution
|
|
13
|
+
* - File editing helpers
|
|
14
|
+
* - Drizzle/ORM utilities
|
|
15
|
+
* - Environment loading
|
|
28
16
|
*/
|
|
29
17
|
export class AlephaCliUtils {
|
|
30
18
|
protected readonly log = $logger();
|
|
31
19
|
protected readonly fs = $inject(FileSystemProvider);
|
|
32
20
|
protected readonly envUtils = $inject(EnvUtils);
|
|
33
|
-
|
|
21
|
+
|
|
22
|
+
// ===========================================
|
|
23
|
+
// Command Execution
|
|
24
|
+
// ===========================================
|
|
34
25
|
|
|
35
26
|
/**
|
|
36
|
-
* Execute a command
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* const runner = alepha.inject(ProcessRunner);
|
|
41
|
-
* await runner.exec("tsx watch src/index.ts");
|
|
42
|
-
* ```
|
|
27
|
+
* Execute a command with inherited stdio.
|
|
43
28
|
*/
|
|
44
29
|
public async exec(
|
|
45
30
|
command: string,
|
|
46
31
|
options: {
|
|
32
|
+
root?: string;
|
|
47
33
|
env?: Record<string, string>;
|
|
48
34
|
global?: boolean;
|
|
49
35
|
} = {},
|
|
50
36
|
): Promise<void> {
|
|
51
|
-
const root = process.cwd();
|
|
37
|
+
const root = options.root ?? process.cwd();
|
|
52
38
|
this.log.debug(`Executing command: ${command}`, { cwd: root });
|
|
53
39
|
|
|
54
40
|
const runExec = async (app: string, args: string[]) => {
|
|
@@ -81,7 +67,6 @@ export class AlephaCliUtils {
|
|
|
81
67
|
let execPath = await this.checkFileExists(
|
|
82
68
|
root,
|
|
83
69
|
`node_modules/.bin/${app}${suffix}`,
|
|
84
|
-
true,
|
|
85
70
|
);
|
|
86
71
|
|
|
87
72
|
// or, find executable inside alepha package node_modules (pnpm style)
|
|
@@ -89,7 +74,6 @@ export class AlephaCliUtils {
|
|
|
89
74
|
execPath = await this.checkFileExists(
|
|
90
75
|
root,
|
|
91
76
|
`node_modules/alepha/node_modules/.bin/${app}${suffix}`,
|
|
92
|
-
true,
|
|
93
77
|
);
|
|
94
78
|
}
|
|
95
79
|
|
|
@@ -104,366 +88,26 @@ export class AlephaCliUtils {
|
|
|
104
88
|
|
|
105
89
|
/**
|
|
106
90
|
* Write a configuration file to node_modules/.alepha directory.
|
|
107
|
-
*
|
|
108
|
-
* Creates the .alepha directory if it doesn't exist and writes the file with the given content.
|
|
109
|
-
*
|
|
110
|
-
* @param name - The name of the config file to create
|
|
111
|
-
* @param content - The content to write to the file
|
|
112
|
-
* @param root - The root directory (defaults to process.cwd())
|
|
113
|
-
* @returns The absolute path to the created file
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* ```ts
|
|
117
|
-
* const runner = alepha.inject(ProcessRunner);
|
|
118
|
-
* const configPath = await runner.writeConfigFile("biome.json", biomeConfig);
|
|
119
|
-
* ```
|
|
120
91
|
*/
|
|
121
92
|
public async writeConfigFile(
|
|
122
93
|
name: string,
|
|
123
94
|
content: string,
|
|
124
95
|
root = process.cwd(),
|
|
125
96
|
): Promise<string> {
|
|
126
|
-
const dir = join(root, "node_modules", ".alepha");
|
|
97
|
+
const dir = this.fs.join(root, "node_modules", ".alepha");
|
|
127
98
|
|
|
128
|
-
await mkdir(dir, {
|
|
129
|
-
recursive: true,
|
|
130
|
-
}).catch(() => null);
|
|
99
|
+
await this.fs.mkdir(dir, { recursive: true }).catch(() => null);
|
|
131
100
|
|
|
132
|
-
const path = join(dir, name);
|
|
133
|
-
await writeFile(path, content);
|
|
101
|
+
const path = this.fs.join(dir, name);
|
|
102
|
+
await this.fs.writeFile(path, content);
|
|
134
103
|
|
|
135
104
|
this.log.debug(`Config file written: ${path}`);
|
|
136
105
|
|
|
137
106
|
return path;
|
|
138
107
|
}
|
|
139
108
|
|
|
140
|
-
// ===================================================================================================================
|
|
141
|
-
// Package Manager & Project Setup
|
|
142
|
-
// ===================================================================================================================
|
|
143
|
-
|
|
144
|
-
public async editFile(
|
|
145
|
-
root: string,
|
|
146
|
-
name: string,
|
|
147
|
-
editFn: (content: string) => string | Promise<string>,
|
|
148
|
-
): Promise<void> {
|
|
149
|
-
const filePath = join(root, name);
|
|
150
|
-
try {
|
|
151
|
-
const content = await readFile(filePath, "utf8");
|
|
152
|
-
const newContent = await editFn(content);
|
|
153
|
-
await writeFile(filePath, newContent);
|
|
154
|
-
} catch (error) {
|
|
155
|
-
this.log.debug("Could not edit file", error);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
public async editJsonFile(
|
|
160
|
-
root: string,
|
|
161
|
-
name: string,
|
|
162
|
-
editFn: (obj: any) => any | Promise<any>,
|
|
163
|
-
): Promise<void> {
|
|
164
|
-
return await this.editFile(root, name, async (content) => {
|
|
165
|
-
const obj = JSON.parse(content);
|
|
166
|
-
const newObj = await editFn(obj);
|
|
167
|
-
return JSON.stringify(newObj, null, 2);
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
public async removeFiles(root: string, files: string[]): Promise<void> {
|
|
172
|
-
await Promise.all(
|
|
173
|
-
files.map((file) =>
|
|
174
|
-
this.fs.rm(join(root, file), { force: true, recursive: true }),
|
|
175
|
-
),
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
public async removeYarn(root: string): Promise<void> {
|
|
180
|
-
await this.removeFiles(root, [".yarn", ".yarnrc.yml", "yarn.lock"]);
|
|
181
|
-
await this.editJsonFile(root, "package.json", (pkg) => {
|
|
182
|
-
delete pkg.packageManager;
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
public async removePnpm(root: string): Promise<void> {
|
|
187
|
-
await this.removeFiles(root, ["pnpm-lock.yaml", "pnpm-workspace.yaml"]);
|
|
188
|
-
await this.editJsonFile(root, "package.json", (pkg) => {
|
|
189
|
-
delete pkg.packageManager;
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
public async removeNpm(root: string): Promise<void> {
|
|
194
|
-
await this.removeFiles(root, ["package-lock.json"]);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
public async removeBun(root: string): Promise<void> {
|
|
198
|
-
await this.removeFiles(root, ["bun.lockb", "bun.lock"]);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
public async removeAllPmFilesExcept(
|
|
202
|
-
root: string,
|
|
203
|
-
except: string,
|
|
204
|
-
): Promise<void> {
|
|
205
|
-
if (except !== "yarn") await this.removeYarn(root);
|
|
206
|
-
if (except !== "pnpm") await this.removePnpm(root);
|
|
207
|
-
if (except !== "npm") await this.removeNpm(root);
|
|
208
|
-
if (except !== "bun") await this.removeBun(root);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Ensure Yarn is configured in the project directory.
|
|
213
|
-
*
|
|
214
|
-
* Creates a .yarnrc.yml file with node-modules linker if it doesn't exist.
|
|
215
|
-
*
|
|
216
|
-
* @param root - The root directory of the project
|
|
217
|
-
*/
|
|
218
|
-
public async ensureYarn(root: string): Promise<void> {
|
|
219
|
-
await this.ensureFileExists(
|
|
220
|
-
root,
|
|
221
|
-
".yarnrc.yml",
|
|
222
|
-
"nodeLinker: node-modules",
|
|
223
|
-
false,
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
await this.removeAllPmFilesExcept(root, "yarn");
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
public async ensureBun(root: string): Promise<void> {
|
|
230
|
-
await this.removeAllPmFilesExcept(root, "bun");
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
public async ensurePnpm(root: string): Promise<void> {
|
|
234
|
-
await this.removeAllPmFilesExcept(root, "pnpm");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
public async ensureNpm(root: string): Promise<void> {
|
|
238
|
-
await this.removeAllPmFilesExcept(root, "npm");
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Generate package.json content with Alepha dependencies.
|
|
243
|
-
*
|
|
244
|
-
* @param modes - Configuration for which dependencies to include
|
|
245
|
-
* @returns Package.json partial with dependencies, devDependencies, and scripts
|
|
246
|
-
*/
|
|
247
|
-
public generatePackageJsonContent(modes: DependencyModes): {
|
|
248
|
-
dependencies: Record<string, string>;
|
|
249
|
-
devDependencies: Record<string, string>;
|
|
250
|
-
scripts: Record<string, string>;
|
|
251
|
-
type: "module";
|
|
252
|
-
} {
|
|
253
|
-
const dependencies: Record<string, string> = {
|
|
254
|
-
alepha: `^${version}`,
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
const devDependencies: Record<string, string> = {};
|
|
258
|
-
|
|
259
|
-
const scripts: Record<string, string> = {
|
|
260
|
-
dev: "alepha dev",
|
|
261
|
-
build: "alepha build",
|
|
262
|
-
lint: "alepha lint",
|
|
263
|
-
typecheck: "alepha typecheck",
|
|
264
|
-
verify: "alepha verify",
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
if (modes.ui) {
|
|
268
|
-
dependencies["@alepha/ui"] = `^${version}`;
|
|
269
|
-
modes.react = true;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (modes.react) {
|
|
273
|
-
dependencies["@alepha/react"] = `^${version}`;
|
|
274
|
-
dependencies.react = "^19.2.0";
|
|
275
|
-
dependencies["react-dom"] = "^19.2.0";
|
|
276
|
-
devDependencies["@types/react"] = "^19.2.0";
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return {
|
|
280
|
-
type: "module",
|
|
281
|
-
dependencies,
|
|
282
|
-
devDependencies,
|
|
283
|
-
scripts,
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Ensure package.json exists and has correct configuration.
|
|
289
|
-
*
|
|
290
|
-
* Creates a new package.json if none exists, or updates an existing one to:
|
|
291
|
-
* - Set "type": "module"
|
|
292
|
-
* - Add Alepha dependencies
|
|
293
|
-
* - Add standard scripts
|
|
294
|
-
*
|
|
295
|
-
* @param root - The root directory of the project
|
|
296
|
-
* @param modes - Configuration for which dependencies to include
|
|
297
|
-
*/
|
|
298
|
-
public async ensurePackageJson(
|
|
299
|
-
root: string,
|
|
300
|
-
modes: DependencyModes,
|
|
301
|
-
): Promise<object> {
|
|
302
|
-
const packageJsonPath = join(root, "package.json");
|
|
303
|
-
try {
|
|
304
|
-
await access(packageJsonPath);
|
|
305
|
-
} catch (error) {
|
|
306
|
-
const obj = this.generatePackageJsonContent(modes);
|
|
307
|
-
await writeFile(packageJsonPath, JSON.stringify(obj, null, 2));
|
|
308
|
-
return obj;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const content = await readFile(packageJsonPath, "utf8");
|
|
312
|
-
const packageJson = JSON.parse(content);
|
|
313
|
-
|
|
314
|
-
const newPackageJson = this.generatePackageJsonContent(modes);
|
|
315
|
-
|
|
316
|
-
packageJson.type = "module";
|
|
317
|
-
packageJson.dependencies ??= {};
|
|
318
|
-
packageJson.devDependencies ??= {};
|
|
319
|
-
packageJson.scripts ??= {};
|
|
320
|
-
|
|
321
|
-
Object.assign(packageJson.dependencies, newPackageJson.dependencies);
|
|
322
|
-
Object.assign(packageJson.devDependencies, newPackageJson.devDependencies);
|
|
323
|
-
Object.assign(packageJson.scripts, newPackageJson.scripts);
|
|
324
|
-
|
|
325
|
-
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
326
|
-
|
|
327
|
-
return packageJson;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
public async ensureConfig(
|
|
331
|
-
root: string,
|
|
332
|
-
opts: {
|
|
333
|
-
packageJson?: boolean | DependencyModes;
|
|
334
|
-
tsconfigJson?: boolean;
|
|
335
|
-
indexHtml?: boolean;
|
|
336
|
-
biomeJson?: boolean;
|
|
337
|
-
editorconfig?: boolean;
|
|
338
|
-
},
|
|
339
|
-
): Promise<Array<void | object>> {
|
|
340
|
-
const tasks: Promise<void | object>[] = [];
|
|
341
|
-
|
|
342
|
-
if (opts.packageJson) {
|
|
343
|
-
tasks.push(
|
|
344
|
-
this.ensurePackageJson(
|
|
345
|
-
root,
|
|
346
|
-
typeof opts.packageJson === "boolean" ? {} : opts.packageJson,
|
|
347
|
-
),
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
if (opts.tsconfigJson) {
|
|
351
|
-
tasks.push(this.ensureTsConfig(root));
|
|
352
|
-
}
|
|
353
|
-
if (opts.indexHtml) {
|
|
354
|
-
tasks.push(this.ensureIndexHtml(root));
|
|
355
|
-
}
|
|
356
|
-
if (opts.biomeJson) {
|
|
357
|
-
tasks.push(this.ensureBiomeConfig(root));
|
|
358
|
-
}
|
|
359
|
-
if (opts.editorconfig) {
|
|
360
|
-
tasks.push(this.ensureEditorConfig(root));
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return await Promise.all(tasks);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Ensure tsconfig.json exists in the project.
|
|
368
|
-
*
|
|
369
|
-
* Creates a standard Alepha tsconfig.json if none exists.
|
|
370
|
-
*
|
|
371
|
-
* @param root - The root directory of the project
|
|
372
|
-
*/
|
|
373
|
-
public async ensureTsConfig(root: string): Promise<void> {
|
|
374
|
-
await this.ensureFileExists(root, "tsconfig.json", tsconfigJson, true);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
protected async checkFileExists(
|
|
378
|
-
root: string,
|
|
379
|
-
name: string,
|
|
380
|
-
checkParentDirectories: boolean = false,
|
|
381
|
-
): Promise<string | undefined> {
|
|
382
|
-
const configPath = join(root, name);
|
|
383
|
-
if (!checkParentDirectories) {
|
|
384
|
-
try {
|
|
385
|
-
await access(configPath);
|
|
386
|
-
return configPath;
|
|
387
|
-
} catch {
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
let currentDir = root;
|
|
393
|
-
const maxIterations = 10; // safety to prevent infinite loops
|
|
394
|
-
let level = 0;
|
|
395
|
-
|
|
396
|
-
while (level < maxIterations) {
|
|
397
|
-
try {
|
|
398
|
-
const maybe = join(currentDir, name);
|
|
399
|
-
await access(maybe);
|
|
400
|
-
return maybe;
|
|
401
|
-
} catch {
|
|
402
|
-
const parentDir = join(currentDir, "..");
|
|
403
|
-
if (parentDir === currentDir) {
|
|
404
|
-
break;
|
|
405
|
-
}
|
|
406
|
-
currentDir = parentDir;
|
|
407
|
-
}
|
|
408
|
-
level += 1;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
protected async ensureFileExists(
|
|
413
|
-
root: string,
|
|
414
|
-
name: string,
|
|
415
|
-
content: string,
|
|
416
|
-
checkParentDirectories: boolean = false,
|
|
417
|
-
): Promise<void> {
|
|
418
|
-
const found = await this.checkFileExists(
|
|
419
|
-
root,
|
|
420
|
-
name,
|
|
421
|
-
checkParentDirectories,
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
if (!found) {
|
|
425
|
-
await writeFile(join(root, name), content);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// ===================================================================================================================
|
|
430
|
-
// Biome Configuration
|
|
431
|
-
// ===================================================================================================================
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Get the path to Biome configuration file.
|
|
435
|
-
*
|
|
436
|
-
* Looks for an existing biome.json in the project root, or creates one if it doesn't exist.
|
|
437
|
-
*/
|
|
438
|
-
public async ensureBiomeConfig(root: string): Promise<void> {
|
|
439
|
-
await this.ensureFileExists(root, "biome.json", biomeJson, true);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
* Ensure .editorconfig exists in the project.
|
|
444
|
-
*
|
|
445
|
-
* Creates a standard .editorconfig if none exists.
|
|
446
|
-
*
|
|
447
|
-
* @param root - The root directory of the project
|
|
448
|
-
*/
|
|
449
|
-
public async ensureEditorConfig(root: string): Promise<void> {
|
|
450
|
-
await this.ensureFileExists(root, ".editorconfig", editorconfig, true);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// ===================================================================================================================
|
|
454
|
-
// Drizzle ORM & Kit Utilities
|
|
455
|
-
// ===================================================================================================================
|
|
456
|
-
|
|
457
109
|
/**
|
|
458
110
|
* Load Alepha instance from a server entry file.
|
|
459
|
-
*
|
|
460
|
-
* Dynamically imports the server entry file and extracts the Alepha instance.
|
|
461
|
-
* Skips the automatic start process.
|
|
462
|
-
*
|
|
463
|
-
* @param rootDir - The root directory of the project
|
|
464
|
-
* @param explicitEntry - Optional explicit path to the entry file
|
|
465
|
-
* @returns Object containing the Alepha instance and the entry file path
|
|
466
|
-
* @throws {AlephaError} If the Alepha instance cannot be found
|
|
467
111
|
*/
|
|
468
112
|
public async loadAlephaFromServerEntryFile(
|
|
469
113
|
rootDir?: string,
|
|
@@ -484,19 +128,13 @@ export class AlephaCliUtils {
|
|
|
484
128
|
|
|
485
129
|
// check if alepha is correctly exported
|
|
486
130
|
if (mod.default instanceof Alepha) {
|
|
487
|
-
return {
|
|
488
|
-
alepha: mod.default,
|
|
489
|
-
entry,
|
|
490
|
-
};
|
|
131
|
+
return { alepha: mod.default, entry };
|
|
491
132
|
}
|
|
492
133
|
|
|
493
134
|
// else, try with global variable
|
|
494
135
|
const g: any = global;
|
|
495
136
|
if (g.__alepha) {
|
|
496
|
-
return {
|
|
497
|
-
alepha: g.__alepha,
|
|
498
|
-
entry,
|
|
499
|
-
};
|
|
137
|
+
return { alepha: g.__alepha, entry };
|
|
500
138
|
}
|
|
501
139
|
|
|
502
140
|
throw new AlephaError(
|
|
@@ -504,16 +142,12 @@ export class AlephaCliUtils {
|
|
|
504
142
|
);
|
|
505
143
|
}
|
|
506
144
|
|
|
145
|
+
// ===========================================
|
|
146
|
+
// Drizzle ORM & Kit Utilities
|
|
147
|
+
// ===========================================
|
|
148
|
+
|
|
507
149
|
/**
|
|
508
150
|
* Generate JavaScript code for Drizzle entities export.
|
|
509
|
-
*
|
|
510
|
-
* Creates a temporary entities.js file that imports from the entry file
|
|
511
|
-
* and exports database models for Drizzle Kit to process.
|
|
512
|
-
*
|
|
513
|
-
* @param entry - Path to the server entry file
|
|
514
|
-
* @param provider - Name of the database provider
|
|
515
|
-
* @param models - Array of model names to export
|
|
516
|
-
* @returns JavaScript code as a string
|
|
517
151
|
*/
|
|
518
152
|
public generateEntitiesJs(
|
|
519
153
|
entry: string,
|
|
@@ -534,11 +168,12 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
|
|
|
534
168
|
`.trim();
|
|
535
169
|
}
|
|
536
170
|
|
|
171
|
+
// ===========================================
|
|
172
|
+
// Environment
|
|
173
|
+
// ===========================================
|
|
174
|
+
|
|
537
175
|
/**
|
|
538
176
|
* Load environment variables from a .env file.
|
|
539
|
-
*
|
|
540
|
-
* Reads the .env file in the specified root directory and sets
|
|
541
|
-
* the environment variables in process.env.
|
|
542
177
|
*/
|
|
543
178
|
public async loadEnv(
|
|
544
179
|
root: string,
|
|
@@ -547,217 +182,21 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
|
|
|
547
182
|
await this.envUtils.loadEnv(root, files);
|
|
548
183
|
}
|
|
549
184
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
): Promise<"yarn" | "pnpm" | "npm" | "bun"> {
|
|
554
|
-
if (flags?.yarn) {
|
|
555
|
-
return "yarn";
|
|
556
|
-
}
|
|
557
|
-
if (flags?.pnpm) {
|
|
558
|
-
return "pnpm";
|
|
559
|
-
}
|
|
560
|
-
if (flags?.npm) {
|
|
561
|
-
return "npm";
|
|
562
|
-
}
|
|
563
|
-
if (flags?.bun) {
|
|
564
|
-
return "bun";
|
|
565
|
-
}
|
|
566
|
-
if (this.alepha.isBun()) {
|
|
567
|
-
return "bun";
|
|
568
|
-
}
|
|
569
|
-
if (await this.checkFileExists(root, "yarn.lock", true)) {
|
|
570
|
-
return "yarn";
|
|
571
|
-
}
|
|
572
|
-
if (await this.checkFileExists(root, "pnpm-lock.yaml", true)) {
|
|
573
|
-
return "pnpm";
|
|
574
|
-
}
|
|
575
|
-
return "npm";
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
public async ensureIndexHtml(root: string) {
|
|
579
|
-
if (await this.fs.exists(join(root, "index.html"))) {
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
const serverEntry = "src/main.server.ts";
|
|
584
|
-
const browserEntry = "src/main.browser.ts";
|
|
585
|
-
const appRouter = "src/AppRouter.ts";
|
|
586
|
-
|
|
587
|
-
await this.fs.writeFile(join(root, "index.html"), indexHtml(browserEntry));
|
|
588
|
-
|
|
589
|
-
try {
|
|
590
|
-
await this.fs.mkdir(join(root, "src"), { recursive: true });
|
|
591
|
-
} catch {}
|
|
185
|
+
// ===========================================
|
|
186
|
+
// Helpers
|
|
187
|
+
// ===========================================
|
|
592
188
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if (!(await this.fs.exists(join(root, serverEntry)))) {
|
|
598
|
-
await this.fs.writeFile(join(root, serverEntry), mainBrowserTs());
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
if (!(await this.fs.exists(join(root, appRouter)))) {
|
|
602
|
-
await this.fs.writeFile(join(root, appRouter), appRouterTs());
|
|
603
|
-
}
|
|
189
|
+
public async exists(root: string, path: string): Promise<boolean> {
|
|
190
|
+
return this.fs.exists(this.fs.join(root, path));
|
|
604
191
|
}
|
|
605
192
|
|
|
606
|
-
|
|
607
|
-
return this.fs.exists(join(root, dirName));
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
* Ensure src/main.ts exists with a minimal Alepha bootstrap.
|
|
612
|
-
*
|
|
613
|
-
* Creates the src directory and main.ts file if the src directory
|
|
614
|
-
* doesn't exist or is empty.
|
|
615
|
-
*
|
|
616
|
-
* @param root - The root directory of the project
|
|
617
|
-
*/
|
|
618
|
-
public async ensureSrcMain(root: string): Promise<void> {
|
|
619
|
-
const srcDir = join(root, "src");
|
|
620
|
-
const mainPath = join(srcDir, "main.ts");
|
|
621
|
-
|
|
622
|
-
// Check if src directory exists
|
|
623
|
-
const srcExists = await this.fs.exists(srcDir);
|
|
624
|
-
|
|
625
|
-
if (!srcExists) {
|
|
626
|
-
// Create src directory and main.ts
|
|
627
|
-
await this.fs.mkdir(srcDir, { recursive: true });
|
|
628
|
-
await this.fs.writeFile(mainPath, mainTs());
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
// Check if src directory is empty
|
|
633
|
-
const files = await this.fs.ls(srcDir);
|
|
634
|
-
if (files.length === 0) {
|
|
635
|
-
await this.fs.writeFile(mainPath, mainTs());
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
/**
|
|
640
|
-
* Ensure test directory exists with a dummy test file.
|
|
641
|
-
*
|
|
642
|
-
* Creates the test directory and a dummy.spec.ts file if the test directory
|
|
643
|
-
* doesn't exist or is empty.
|
|
644
|
-
*
|
|
645
|
-
* @param root - The root directory of the project
|
|
646
|
-
*/
|
|
647
|
-
public async ensureTestDir(root: string): Promise<void> {
|
|
648
|
-
const testDir = join(root, "test");
|
|
649
|
-
const dummyPath = join(testDir, "dummy.spec.ts");
|
|
650
|
-
|
|
651
|
-
// Check if test directory exists
|
|
652
|
-
const testExists = await this.fs.exists(testDir);
|
|
653
|
-
|
|
654
|
-
if (!testExists) {
|
|
655
|
-
// Create test directory and dummy.spec.ts
|
|
656
|
-
await this.fs.mkdir(testDir, { recursive: true });
|
|
657
|
-
await this.fs.writeFile(dummyPath, dummySpecTs());
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// Check if test directory is empty
|
|
662
|
-
const files = await this.fs.ls(testDir);
|
|
663
|
-
if (files.length === 0) {
|
|
664
|
-
await this.fs.writeFile(dummyPath, dummySpecTs());
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
async readPackageJson(root: string): Promise<Record<string, any>> {
|
|
669
|
-
const packageJson = await this.fs
|
|
670
|
-
.createFile({
|
|
671
|
-
path: this.fs.join(root, "package.json"),
|
|
672
|
-
})
|
|
673
|
-
.text();
|
|
674
|
-
return JSON.parse(packageJson);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
/**
|
|
678
|
-
* Check if a dependency is installed in the project.
|
|
679
|
-
*
|
|
680
|
-
* @param root - The root directory of the project
|
|
681
|
-
* @param packageName - The name of the package to check
|
|
682
|
-
* @returns True if the package is in dependencies or devDependencies
|
|
683
|
-
*/
|
|
684
|
-
async hasDependency(root: string, packageName: string): Promise<boolean> {
|
|
685
|
-
try {
|
|
686
|
-
const pkg = await this.readPackageJson(root);
|
|
687
|
-
return !!(
|
|
688
|
-
pkg.dependencies?.[packageName] || pkg.devDependencies?.[packageName]
|
|
689
|
-
);
|
|
690
|
-
} catch {
|
|
691
|
-
return false;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
/**
|
|
696
|
-
* Check if Expo is present in the project.
|
|
697
|
-
*
|
|
698
|
-
* @param root - The root directory of the project
|
|
699
|
-
* @returns True if expo is in dependencies or devDependencies
|
|
700
|
-
*/
|
|
701
|
-
async hasExpo(root: string): Promise<boolean> {
|
|
702
|
-
return this.hasDependency(root, "expo");
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
async getInstallCommand(root: string, packageName: string, dev = true) {
|
|
706
|
-
const pm = await this.getPackageManager(root);
|
|
707
|
-
let cmd: string;
|
|
708
|
-
|
|
709
|
-
switch (pm) {
|
|
710
|
-
case "yarn":
|
|
711
|
-
cmd = `yarn add ${dev ? "-D" : ""} ${packageName}`;
|
|
712
|
-
break;
|
|
713
|
-
case "pnpm":
|
|
714
|
-
cmd = `pnpm add ${dev ? "-D" : ""} ${packageName}`;
|
|
715
|
-
break;
|
|
716
|
-
case "bun":
|
|
717
|
-
cmd = `bun add ${dev ? "-d" : ""} ${packageName}`;
|
|
718
|
-
break;
|
|
719
|
-
default:
|
|
720
|
-
cmd = `npm install ${dev ? "--save-dev" : ""} ${packageName}`;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
return cmd.replace(/\s+/g, " ").trim();
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
/**
|
|
727
|
-
* Install a dependency if it's missing from the project.
|
|
728
|
-
*
|
|
729
|
-
* Automatically detects the package manager (yarn, pnpm, npm) and installs
|
|
730
|
-
* the package as a dev dependency if not already present.
|
|
731
|
-
*/
|
|
732
|
-
async ensureDependency(
|
|
193
|
+
protected async checkFileExists(
|
|
733
194
|
root: string,
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
if (await this.hasDependency(root, packageName)) {
|
|
740
|
-
this.log.debug(`Dependency '${packageName}' is already installed`);
|
|
741
|
-
return;
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
const cmd = await this.getInstallCommand(root, packageName, dev);
|
|
745
|
-
|
|
746
|
-
if (options.run) {
|
|
747
|
-
// if it's during a Runner flow, just use the runner's run method
|
|
748
|
-
await options.run(cmd, {
|
|
749
|
-
alias: `installing ${packageName}`,
|
|
750
|
-
});
|
|
751
|
-
} else {
|
|
752
|
-
// else, run directly with our util exec method
|
|
753
|
-
this.log.debug(`Installing ${packageName}`);
|
|
754
|
-
await this.exec(cmd, { global: true });
|
|
195
|
+
name: string,
|
|
196
|
+
): Promise<string | undefined> {
|
|
197
|
+
const configPath = this.fs.join(root, name);
|
|
198
|
+
if (await this.fs.exists(configPath)) {
|
|
199
|
+
return configPath;
|
|
755
200
|
}
|
|
756
201
|
}
|
|
757
202
|
}
|
|
758
|
-
|
|
759
|
-
export interface DependencyModes {
|
|
760
|
-
react?: boolean;
|
|
761
|
-
ui?: boolean;
|
|
762
|
-
expo?: boolean;
|
|
763
|
-
}
|