@mittwald/cli 1.9.1 → 1.11.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/bin/run.js +4 -1
- package/dist/commands/app/create/node.d.ts +1 -3
- package/dist/commands/app/create/php-worker.d.ts +1 -3
- package/dist/commands/app/create/php.d.ts +1 -3
- package/dist/commands/app/create/python.d.ts +1 -3
- package/dist/commands/app/create/static.d.ts +1 -3
- package/dist/commands/app/dependency/update.js +2 -4
- package/dist/commands/app/download.js +2 -2
- package/dist/commands/app/exec.d.ts +17 -0
- package/dist/commands/app/exec.js +71 -0
- package/dist/commands/app/install/contao.d.ts +1 -3
- package/dist/commands/app/install/joomla.d.ts +1 -3
- package/dist/commands/app/install/matomo.d.ts +1 -3
- package/dist/commands/app/install/nextcloud.d.ts +1 -3
- package/dist/commands/app/install/shopware5.d.ts +1 -3
- package/dist/commands/app/install/shopware6.d.ts +1 -3
- package/dist/commands/app/install/typo3.d.ts +1 -3
- package/dist/commands/app/install/wordpress.d.ts +1 -3
- package/dist/commands/app/ssh.d.ts +1 -0
- package/dist/commands/app/ssh.js +15 -1
- package/dist/commands/app/update.js +4 -8
- package/dist/commands/app/upgrade.js +9 -9
- package/dist/commands/backup/create.js +1 -2
- package/dist/commands/backup/download.js +4 -5
- package/dist/commands/container/exec.d.ts +1 -7
- package/dist/commands/container/exec.js +11 -22
- package/dist/commands/container/run.d.ts +4 -2
- package/dist/commands/container/run.js +7 -6
- package/dist/commands/database/mysql/create.js +1 -2
- package/dist/commands/database/mysql/dump.js +1 -2
- package/dist/commands/database/mysql/import.js +1 -2
- package/dist/commands/ddev/init.js +2 -6
- package/dist/commands/extension/install.js +1 -3
- package/dist/commands/login/reset.js +1 -2
- package/dist/commands/mail/address/create.js +1 -4
- package/dist/commands/mail/deliverybox/create.js +1 -4
- package/dist/commands/project/create.js +4 -6
- package/dist/commands/registry/create.js +1 -2
- package/dist/commands/registry/update.js +1 -2
- package/dist/commands/user/api-token/create.js +1 -1
- package/dist/commands/user/ssh-key/create.js +3 -8
- package/dist/commands/user/ssh-key/import.js +2 -3
- package/dist/hooks/prerun/update-brew-check.js +1 -1
- package/dist/lib/basecommands/DeleteBaseCommand.js +4 -4
- package/dist/lib/ddev/init_assert.js +1 -6
- package/dist/lib/ddev/init_database.js +1 -7
- package/dist/lib/ddev/init_projecttype.js +2 -11
- package/dist/lib/intellij/config.d.ts +5 -0
- package/dist/lib/intellij/config.js +295 -0
- package/dist/lib/intellij/config.test.d.ts +1 -0
- package/dist/lib/intellij/config.test.js +262 -0
- package/dist/lib/intellij/config_xml_types.d.ts +72 -0
- package/dist/lib/intellij/config_xml_types.js +2 -0
- package/dist/lib/resources/app/Installer.d.ts +6 -2
- package/dist/lib/resources/app/Installer.js +13 -6
- package/dist/lib/resources/app/flags.js +9 -12
- package/dist/lib/resources/app/install.d.ts +2 -1
- package/dist/lib/resources/app/install.js +3 -1
- package/dist/lib/resources/app/versions.js +1 -4
- package/dist/lib/resources/app/wait.js +1 -3
- package/dist/lib/resources/mail/commons.js +1 -4
- package/dist/lib/resources/ssh/appinstall.d.ts +3 -1
- package/dist/lib/resources/ssh/appinstall.js +1 -0
- package/dist/lib/resources/ssh/environment.d.ts +7 -0
- package/dist/lib/resources/ssh/environment.js +21 -0
- package/dist/rendering/process/components/ProcessStateIcon.js +1 -1
- package/dist/rendering/process/process.d.ts +16 -16
- package/dist/rendering/process/process_exec.d.ts +1 -2
- package/dist/rendering/process/process_fancy.d.ts +9 -9
- package/dist/rendering/process/process_flags.js +4 -0
- package/dist/rendering/process/process_quiet.d.ts +3 -4
- package/dist/rendering/process/process_simple.d.ts +26 -0
- package/dist/rendering/process/process_simple.js +143 -0
- package/dist/rendering/process/process_simple.test.d.ts +1 -0
- package/dist/rendering/process/process_simple.test.js +149 -0
- package/dist/rendering/react/components/AppInstallation/AppBackendAccessHints.d.ts +15 -0
- package/dist/rendering/react/components/AppInstallation/AppBackendAccessHints.js +13 -0
- package/dist/rendering/react/components/AppInstallation/AppDomainConnectionHints.d.ts +12 -0
- package/dist/rendering/react/components/AppInstallation/AppDomainConnectionHints.js +21 -0
- package/dist/rendering/react/components/AppInstallation/AppManagementCommands.d.ts +12 -0
- package/dist/rendering/react/components/AppInstallation/AppManagementCommands.js +17 -0
- package/dist/rendering/react/components/AppInstallation/AppUsageHints.d.ts +17 -0
- package/dist/rendering/react/components/AppInstallation/AppUsageHints.js +23 -0
- package/dist/rendering/react/components/Container/CommandHint.d.ts +14 -0
- package/dist/rendering/react/components/Container/CommandHint.js +13 -0
- package/dist/rendering/react/components/Container/ContainerManagementCommands.d.ts +22 -0
- package/dist/rendering/react/components/Container/ContainerManagementCommands.js +23 -0
- package/dist/rendering/react/components/Container/ContainerUsageHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/ContainerUsageHints.js +35 -0
- package/dist/rendering/react/components/Container/DomainConnectionHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/DomainConnectionHints.js +21 -0
- package/dist/rendering/react/components/Container/InternalConnectionHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/InternalConnectionHints.js +12 -0
- package/dist/rendering/react/components/Container/NoPortsUsageHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/NoPortsUsageHints.js +12 -0
- package/dist/rendering/react/components/Container/PortConnectionHints.d.ts +13 -0
- package/dist/rendering/react/components/Container/PortConnectionHints.js +11 -0
- package/dist/rendering/react/components/Container/PortForwardingHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/PortForwardingHints.js +18 -0
- package/dist/rendering/react/components/Container/types.d.ts +4 -0
- package/dist/rendering/react/components/Container/types.js +1 -0
- package/dist/rendering/react/components/Error/ErrorBox.d.ts +1 -1
- package/dist/rendering/react/components/Error/ErrorBox.js +3 -4
- package/dist/rendering/react/components/Error/GenericError.js +1 -1
- package/dist/rendering/react/components/ErrorBoundary.d.ts +1 -1
- package/dist/rendering/react/components/Success.d.ts +0 -1
- package/dist/rendering/react/components/Success.js +4 -2
- package/dist/rendering/react/styles/useDefaultBoxStyles.d.ts +11 -0
- package/dist/rendering/react/styles/useDefaultBoxStyles.js +23 -0
- package/package.json +6 -5
|
@@ -6,6 +6,7 @@ import { normalizeToAppVersionUuid } from "./versions.js";
|
|
|
6
6
|
import { triggerAppInstallation } from "./install.js";
|
|
7
7
|
import { waitUntilAppStateHasNormalized } from "./wait.js";
|
|
8
8
|
import { Success } from "../../../rendering/react/components/Success.js";
|
|
9
|
+
import AppUsageHints from "../../../rendering/react/components/AppInstallation/AppUsageHints.js";
|
|
9
10
|
export class AppInstaller {
|
|
10
11
|
appId;
|
|
11
12
|
appName;
|
|
@@ -35,22 +36,28 @@ export class AppInstaller {
|
|
|
35
36
|
const projectId = await withProjectId(apiClient, "flag", flags, args, config);
|
|
36
37
|
await autofillFlags(apiClient, process, this.appSupportedFlags, flags, projectId, this.appName, this.defaultFlagValues);
|
|
37
38
|
const appVersion = await normalizeToAppVersionUuid(apiClient, "version" in flags ? flags.version : "latest", process, this.appId);
|
|
38
|
-
const
|
|
39
|
+
const appInstallation = await triggerAppInstallation(apiClient, process, projectId, flags, appVersion);
|
|
39
40
|
let successText;
|
|
40
41
|
if (flags.wait) {
|
|
41
|
-
await waitUntilAppStateHasNormalized(apiClient, process,
|
|
42
|
+
await waitUntilAppStateHasNormalized(apiClient, process, appInstallation.id, "waiting for app installation to be ready", flags["wait-timeout"]);
|
|
42
43
|
successText = `Your ${this.appName} installation is now complete. Have fun! 🎉`;
|
|
43
44
|
}
|
|
44
45
|
else {
|
|
45
46
|
successText = `Your ${this.appName} installation has started. Have fun when it's ready! 🎉`;
|
|
46
47
|
}
|
|
47
|
-
process.complete(_jsx(Success, { children: successText }));
|
|
48
|
-
return {
|
|
48
|
+
await process.complete(_jsx(Success, { children: successText }));
|
|
49
|
+
return {
|
|
50
|
+
appInstallation,
|
|
51
|
+
appVersion,
|
|
52
|
+
host: "host" in flags && typeof flags.host === "string"
|
|
53
|
+
? flags.host
|
|
54
|
+
: undefined,
|
|
55
|
+
};
|
|
49
56
|
}
|
|
50
57
|
render(result, flags) {
|
|
51
58
|
if (flags.quiet) {
|
|
52
|
-
return result.
|
|
59
|
+
return result.appInstallation.id;
|
|
53
60
|
}
|
|
54
|
-
return
|
|
61
|
+
return (_jsx(AppUsageHints, { appInstallation: result.appInstallation, appVersion: result.appVersion, appName: this.appName, appHost: result.host }));
|
|
55
62
|
}
|
|
56
63
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
1
|
import { getDefaultIngressForProject } from "../project/ingress.js";
|
|
3
|
-
import { Value } from "../../../rendering/react/components/Value.js";
|
|
4
2
|
import { getProjectShortIdFromUuid } from "../project/shortId.js";
|
|
5
|
-
import { Text } from "ink";
|
|
6
3
|
import { assertStatus } from "@mittwald/api-client-commons";
|
|
7
4
|
import { projectFlags } from "../project/flags.js";
|
|
8
5
|
import { processFlags, } from "../../../rendering/process/process_flags.js";
|
|
@@ -169,7 +166,7 @@ export async function autofillFlags(apiClient, process, necessaryFlags, flags, p
|
|
|
169
166
|
if (necessaryFlags.includes("host") && !flags.host) {
|
|
170
167
|
flags.host =
|
|
171
168
|
"https://" + (await getDefaultIngressForProject(apiClient, projectId));
|
|
172
|
-
process.addInfo(
|
|
169
|
+
process.addInfo(`Using default Host ${flags["host"]}`);
|
|
173
170
|
}
|
|
174
171
|
// Title
|
|
175
172
|
if (necessaryFlags.includes("site-title") && !flags["site-title"]) {
|
|
@@ -186,12 +183,12 @@ export async function autofillFlags(apiClient, process, necessaryFlags, flags, p
|
|
|
186
183
|
else {
|
|
187
184
|
flags["admin-user"] = await getProjectShortIdFromUuid(apiClient, projectId);
|
|
188
185
|
}
|
|
189
|
-
process.addInfo(
|
|
186
|
+
process.addInfo(`Using generated Admin User: ${flags["admin-user"]}`);
|
|
190
187
|
}
|
|
191
188
|
// Admin Pass
|
|
192
189
|
if (necessaryFlags.includes("admin-pass") && !flags["admin-pass"]) {
|
|
193
190
|
flags["admin-pass"] = generatePasswordWithSpecialChars();
|
|
194
|
-
process.addInfo(
|
|
191
|
+
process.addInfo(`Using generated random Admin Pass: ${flags["admin-pass"]}`);
|
|
195
192
|
}
|
|
196
193
|
// Admin Firstname
|
|
197
194
|
if (necessaryFlags.includes("admin-firstname") && !flags["admin-firstname"]) {
|
|
@@ -201,7 +198,7 @@ export async function autofillFlags(apiClient, process, necessaryFlags, flags, p
|
|
|
201
198
|
else {
|
|
202
199
|
flags["admin-firstname"] = "Max";
|
|
203
200
|
}
|
|
204
|
-
process.addInfo(
|
|
201
|
+
process.addInfo(`Using mStudio firstname as Admin firstname (${flags["admin-firstname"]})`);
|
|
205
202
|
}
|
|
206
203
|
// Admin Lastname
|
|
207
204
|
if (necessaryFlags.includes("admin-lastname") && !flags["admin-lastname"]) {
|
|
@@ -211,26 +208,26 @@ export async function autofillFlags(apiClient, process, necessaryFlags, flags, p
|
|
|
211
208
|
else {
|
|
212
209
|
flags["admin-lastname"] = "Mustermann";
|
|
213
210
|
}
|
|
214
|
-
process.addInfo(
|
|
211
|
+
process.addInfo(`Using mStudio lastname as Admin lastname (${flags["admin-lastname"]})`);
|
|
215
212
|
}
|
|
216
213
|
// Admin E-Mail
|
|
217
214
|
if (necessaryFlags.includes("admin-email") && !flags["admin-email"]) {
|
|
218
215
|
flags["admin-email"] = ownUser.data.email;
|
|
219
|
-
process.addInfo(
|
|
216
|
+
process.addInfo(`Using mStudio email as Admin email (${flags["admin-email"]})`);
|
|
220
217
|
}
|
|
221
218
|
// Shop E-Mail
|
|
222
219
|
if (necessaryFlags.includes("shop-email") && !flags["shop-email"]) {
|
|
223
220
|
flags["shop-email"] = ownUser.data.email;
|
|
224
|
-
process.addInfo(
|
|
221
|
+
process.addInfo(`Using mStudio email as Shop email (${flags["shop-email"]})`);
|
|
225
222
|
}
|
|
226
223
|
// Shop Language Code
|
|
227
224
|
if (necessaryFlags.includes("shop-lang") && !flags["shop-lang"]) {
|
|
228
225
|
flags["shop-lang"] = defaults["shop-lang"] ?? "de-DE";
|
|
229
|
-
process.addInfo(
|
|
226
|
+
process.addInfo(`Using default shop language '${flags["shop-lang"]}'.`);
|
|
230
227
|
}
|
|
231
228
|
// Shop Currency
|
|
232
229
|
if (necessaryFlags.includes("shop-currency") && !flags["shop-currency"]) {
|
|
233
230
|
flags["shop-currency"] = "EUR";
|
|
234
|
-
process.addInfo(
|
|
231
|
+
process.addInfo("Using default shop currency '€'.");
|
|
235
232
|
}
|
|
236
233
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { MittwaldAPIV2, MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
2
2
|
import { ProcessRenderer } from "../../../rendering/process/process.js";
|
|
3
|
+
type AppAppInstallation = MittwaldAPIV2.Components.Schemas.AppAppInstallation;
|
|
3
4
|
type AppAppVersion = MittwaldAPIV2.Components.Schemas.AppAppVersion;
|
|
4
5
|
export declare function triggerAppInstallation(apiClient: MittwaldAPIV2Client, process: ProcessRenderer, projectId: string, flags: {
|
|
5
6
|
"site-title": string;
|
|
6
7
|
"document-root"?: string;
|
|
7
8
|
} & {
|
|
8
9
|
[k: string]: unknown;
|
|
9
|
-
}, appVersion: AppAppVersion): Promise<
|
|
10
|
+
}, appVersion: AppAppVersion): Promise<AppAppInstallation>;
|
|
10
11
|
export {};
|
|
@@ -38,5 +38,7 @@ export async function triggerAppInstallation(apiClient, process, projectId, flag
|
|
|
38
38
|
assertStatus(result, 204);
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
const result = await apiClient.app.getAppinstallation({ appInstallationId });
|
|
42
|
+
assertStatus(result, 200);
|
|
43
|
+
return result.data;
|
|
42
44
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
1
|
import { assertStatus } from "@mittwald/api-client-commons";
|
|
3
2
|
import { gt } from "semver";
|
|
4
|
-
import { Value } from "../../../rendering/react/components/Value.js";
|
|
5
|
-
import { Text } from "ink";
|
|
6
3
|
import { getAppInstallationFromUuid, getAppNameFromUuid } from "./uuid.js";
|
|
7
4
|
import { compare } from "semver";
|
|
8
5
|
export async function normalizeToAppVersionUuid(apiClient, version, process, appUuid) {
|
|
@@ -16,7 +13,7 @@ export async function normalizeToAppVersionUuid(apiClient, version, process, app
|
|
|
16
13
|
if (!appVersion) {
|
|
17
14
|
throw new Error(`${await getAppNameFromUuid(apiClient, appUuid)} version ${version} does not seem to exist for the mStudio.`);
|
|
18
15
|
}
|
|
19
|
-
process.addInfo(
|
|
16
|
+
process.addInfo(`installing version: ${appVersion.externalVersion}`);
|
|
20
17
|
return appVersion;
|
|
21
18
|
}
|
|
22
19
|
// Get latest available Internal App Version for App UUID
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
1
|
import { waitUntil } from "../../wait.js";
|
|
3
|
-
import { Text } from "ink";
|
|
4
2
|
export async function waitUntilAppStateHasNormalized(apiClient, process, appInstallationId, label, timeout) {
|
|
5
|
-
const stepWaiting = process.addStep(
|
|
3
|
+
const stepWaiting = process.addStep(label);
|
|
6
4
|
await waitUntil(async () => {
|
|
7
5
|
const installationResponse = await apiClient.app.getAppinstallation({
|
|
8
6
|
appInstallationId,
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
1
|
import { generatePassword } from "../../util/password/generatePassword.js";
|
|
3
|
-
import { Value } from "../../../rendering/react/components/Value.js";
|
|
4
|
-
import { Text } from "ink";
|
|
5
2
|
export async function generateRandomPassword(process) {
|
|
6
3
|
const generated = await process.runStep("generating random password", async () => generatePassword(32));
|
|
7
|
-
process.addInfo(
|
|
4
|
+
process.addInfo(` generated password: ${generated} `);
|
|
8
5
|
return generated;
|
|
9
6
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
2
2
|
import { SSHConnectionData } from "./types.js";
|
|
3
|
-
export declare function getSSHConnectionForAppInstallation(client: MittwaldAPIV2Client, appInstallationId: string, sshUser: string | undefined): Promise<SSHConnectionData
|
|
3
|
+
export declare function getSSHConnectionForAppInstallation(client: MittwaldAPIV2Client, appInstallationId: string, sshUser: string | undefined): Promise<SSHConnectionData & {
|
|
4
|
+
appShortId: string;
|
|
5
|
+
}>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prepare environment variables for SSH command execution
|
|
3
|
+
*
|
|
4
|
+
* @param envVars Array of environment variables in KEY=VALUE format
|
|
5
|
+
* @returns Formatted string with export commands
|
|
6
|
+
*/
|
|
7
|
+
export declare function prepareEnvironmentVariables(envVars: string[]): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import shellEscape from "shell-escape";
|
|
2
|
+
/**
|
|
3
|
+
* Prepare environment variables for SSH command execution
|
|
4
|
+
*
|
|
5
|
+
* @param envVars Array of environment variables in KEY=VALUE format
|
|
6
|
+
* @returns Formatted string with export commands
|
|
7
|
+
*/
|
|
8
|
+
export function prepareEnvironmentVariables(envVars) {
|
|
9
|
+
return (envVars
|
|
10
|
+
.map((env) => {
|
|
11
|
+
const eqIdx = env.indexOf("=");
|
|
12
|
+
if (eqIdx === -1) {
|
|
13
|
+
// If no '=', treat the whole string as key with empty value
|
|
14
|
+
return `export ${shellEscape([env])}=`;
|
|
15
|
+
}
|
|
16
|
+
const key = env.slice(0, eqIdx);
|
|
17
|
+
const value = env.slice(eqIdx + 1);
|
|
18
|
+
return `export ${shellEscape([key])}=${shellEscape([value])}`;
|
|
19
|
+
})
|
|
20
|
+
.join("; ") + "; ");
|
|
21
|
+
}
|
|
@@ -10,7 +10,7 @@ export const ProcessStateIcon = ({ step }) => {
|
|
|
10
10
|
return _jsx(Text, { children: "\u2753" });
|
|
11
11
|
}
|
|
12
12
|
else if (step.phase === "completed") {
|
|
13
|
-
return _jsx(Text, { children: "\u2705" });
|
|
13
|
+
return _jsx(Text, { children: "\u2705 " });
|
|
14
14
|
}
|
|
15
15
|
else if (step.phase === "aborted") {
|
|
16
16
|
return _jsx(Text, { children: "\u23E9\uFE0F " });
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ReactElement
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
2
|
export type ProcessStepInfo = {
|
|
3
3
|
type: "info";
|
|
4
|
-
title:
|
|
4
|
+
title: string;
|
|
5
5
|
};
|
|
6
6
|
export type ProcessStepRunnable = {
|
|
7
7
|
type: "step";
|
|
8
|
-
title:
|
|
8
|
+
title: string;
|
|
9
9
|
phase: "running" | "completed" | "failed" | "aborted";
|
|
10
10
|
error?: unknown;
|
|
11
11
|
progress?: string;
|
|
@@ -13,27 +13,27 @@ export type ProcessStepRunnable = {
|
|
|
13
13
|
};
|
|
14
14
|
export type ProcessStepConfirm = {
|
|
15
15
|
type: "confirm";
|
|
16
|
-
title:
|
|
16
|
+
title: string;
|
|
17
17
|
confirmed: boolean | undefined;
|
|
18
18
|
};
|
|
19
19
|
export type ProcessStepInput = {
|
|
20
20
|
type: "input";
|
|
21
|
-
title:
|
|
21
|
+
title: string;
|
|
22
22
|
mask?: boolean;
|
|
23
23
|
value?: string;
|
|
24
24
|
};
|
|
25
25
|
export type ProcessStepSelect<TVal> = {
|
|
26
26
|
type: "select";
|
|
27
|
-
title:
|
|
27
|
+
title: string;
|
|
28
28
|
options: {
|
|
29
29
|
value: TVal;
|
|
30
|
-
label:
|
|
30
|
+
label: string;
|
|
31
31
|
}[];
|
|
32
32
|
selected?: TVal;
|
|
33
33
|
};
|
|
34
34
|
export type ProcessStep = ProcessStepInfo | ProcessStepRunnable | ProcessStepConfirm | ProcessStepInput | ProcessStepSelect<unknown>;
|
|
35
35
|
export type CleanupFunction = {
|
|
36
|
-
title:
|
|
36
|
+
title: string;
|
|
37
37
|
fn: () => Promise<unknown>;
|
|
38
38
|
};
|
|
39
39
|
export declare class RunnableHandler {
|
|
@@ -53,16 +53,16 @@ export declare class RunnableHandler {
|
|
|
53
53
|
}
|
|
54
54
|
export interface ProcessRenderer {
|
|
55
55
|
start(): void;
|
|
56
|
-
addStep(title:
|
|
57
|
-
runStep<TRes>(title:
|
|
58
|
-
addInfo(title:
|
|
59
|
-
addConfirmation(question:
|
|
60
|
-
addInput(question:
|
|
61
|
-
addSelect<TVal>(question:
|
|
56
|
+
addStep(title: string): RunnableHandler;
|
|
57
|
+
runStep<TRes>(title: string, fn: (() => Promise<TRes>) | Promise<TRes>): Promise<TRes>;
|
|
58
|
+
addInfo(title: string): void;
|
|
59
|
+
addConfirmation(question: string): Promise<boolean>;
|
|
60
|
+
addInput(question: string, mask?: boolean): Promise<string>;
|
|
61
|
+
addSelect<TVal>(question: string, options: {
|
|
62
62
|
value: TVal;
|
|
63
|
-
label:
|
|
63
|
+
label: string;
|
|
64
64
|
}[]): Promise<TVal>;
|
|
65
|
-
addCleanup(title:
|
|
65
|
+
addCleanup(title: string, fn: () => Promise<unknown>): void;
|
|
66
66
|
complete(summary: ReactElement): Promise<void>;
|
|
67
67
|
error(err: unknown): Promise<void>;
|
|
68
68
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { ProcessRenderer } from "./process.js";
|
|
2
|
-
|
|
3
|
-
export declare function spawnInProcess(r: ProcessRenderer, title: ReactNode, cmd: string, args: string[]): Promise<void>;
|
|
2
|
+
export declare function spawnInProcess(r: ProcessRenderer, title: string, cmd: string, args: string[]): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
2
|
import { ProcessRenderer, RunnableHandler } from "./process.js";
|
|
3
3
|
export declare class FancyProcessRenderer implements ProcessRenderer {
|
|
4
4
|
private readonly title;
|
|
@@ -7,18 +7,18 @@ export declare class FancyProcessRenderer implements ProcessRenderer {
|
|
|
7
7
|
private cleanupFns;
|
|
8
8
|
constructor(title: string);
|
|
9
9
|
start(): void;
|
|
10
|
-
addStep(title:
|
|
11
|
-
runStep<TRes>(title:
|
|
12
|
-
addInfo(title:
|
|
13
|
-
addInput(question:
|
|
14
|
-
addSelect<TVal>(question:
|
|
10
|
+
addStep(title: string): RunnableHandler;
|
|
11
|
+
runStep<TRes>(title: string, fn: (() => Promise<TRes>) | Promise<TRes>): Promise<TRes>;
|
|
12
|
+
addInfo(title: string): void;
|
|
13
|
+
addInput(question: string, mask?: boolean): Promise<string>;
|
|
14
|
+
addSelect<TVal>(question: string, options: {
|
|
15
15
|
value: TVal;
|
|
16
|
-
label:
|
|
16
|
+
label: string;
|
|
17
17
|
}[]): Promise<TVal>;
|
|
18
|
-
addConfirmation(question:
|
|
18
|
+
addConfirmation(question: string): Promise<boolean>;
|
|
19
19
|
complete(summary: ReactElement): Promise<void>;
|
|
20
20
|
error(err: unknown): Promise<void>;
|
|
21
21
|
private renderStart;
|
|
22
|
-
addCleanup(title:
|
|
22
|
+
addCleanup(title: string, fn: () => Promise<unknown>): void;
|
|
23
23
|
private cleanup;
|
|
24
24
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FancyProcessRenderer } from "./process_fancy.js";
|
|
2
2
|
import { Flags } from "@oclif/core";
|
|
3
3
|
import { SilentProcessRenderer } from "./process_quiet.js";
|
|
4
|
+
import { SimpleProcessRenderer } from "./process_simple.js";
|
|
4
5
|
export const processFlags = {
|
|
5
6
|
quiet: Flags.boolean({
|
|
6
7
|
char: "q",
|
|
@@ -25,5 +26,8 @@ export const makeProcessRenderer = (flags, title) => {
|
|
|
25
26
|
if (flags.quiet) {
|
|
26
27
|
return new SilentProcessRenderer();
|
|
27
28
|
}
|
|
29
|
+
if (!process.stdout.isTTY) {
|
|
30
|
+
return new SimpleProcessRenderer(title, process.stdout);
|
|
31
|
+
}
|
|
28
32
|
return new FancyProcessRenderer(title);
|
|
29
33
|
};
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
1
|
import { ProcessRenderer, RunnableHandler } from "./process.js";
|
|
3
2
|
export declare class SilentProcessRenderer implements ProcessRenderer {
|
|
4
3
|
private cleanupFns;
|
|
5
4
|
start(): void;
|
|
6
|
-
addStep(title:
|
|
7
|
-
runStep<TRes>(unusedTitle:
|
|
5
|
+
addStep(title: string): RunnableHandler;
|
|
6
|
+
runStep<TRes>(unusedTitle: string, fn: (() => Promise<TRes>) | Promise<TRes>): Promise<TRes>;
|
|
8
7
|
addInfo(): void;
|
|
9
8
|
complete(): Promise<void>;
|
|
10
9
|
error(err: unknown): Promise<void>;
|
|
11
10
|
addConfirmation(): Promise<boolean>;
|
|
12
11
|
addInput(): Promise<string>;
|
|
13
12
|
addSelect<TVal>(): Promise<TVal>;
|
|
14
|
-
addCleanup(_:
|
|
13
|
+
addCleanup(_: string, fn: () => Promise<unknown>): void;
|
|
15
14
|
private cleanup;
|
|
16
15
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { ProcessRenderer, RunnableHandler } from "./process.js";
|
|
3
|
+
import { Writable } from "stream";
|
|
4
|
+
export declare class SimpleProcessRenderer implements ProcessRenderer {
|
|
5
|
+
private readonly title;
|
|
6
|
+
private readonly output;
|
|
7
|
+
private started;
|
|
8
|
+
private cleanupFns;
|
|
9
|
+
private stepCounter;
|
|
10
|
+
constructor(title: string, output: Writable);
|
|
11
|
+
start(): void;
|
|
12
|
+
addStep(title: string): RunnableHandler;
|
|
13
|
+
runStep<TRes>(title: string, fn: (() => Promise<TRes>) | Promise<TRes>): Promise<TRes>;
|
|
14
|
+
addInfo(title: string): void;
|
|
15
|
+
addConfirmation(question: string): Promise<boolean>;
|
|
16
|
+
addInput(question: string, mask?: boolean): Promise<string>;
|
|
17
|
+
addSelect<TVal>(question: string, options: {
|
|
18
|
+
value: TVal;
|
|
19
|
+
label: string;
|
|
20
|
+
}[]): Promise<TVal>;
|
|
21
|
+
addCleanup(title: string, fn: () => Promise<unknown>): void;
|
|
22
|
+
complete(summary: ReactElement): Promise<void>;
|
|
23
|
+
error(err: unknown): Promise<void>;
|
|
24
|
+
private cleanup;
|
|
25
|
+
private renderElementToText;
|
|
26
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { RunnableHandler, } from "./process.js";
|
|
2
|
+
export class SimpleProcessRenderer {
|
|
3
|
+
title;
|
|
4
|
+
output;
|
|
5
|
+
started = false;
|
|
6
|
+
cleanupFns = [];
|
|
7
|
+
stepCounter = 0;
|
|
8
|
+
constructor(title, output) {
|
|
9
|
+
this.title = title;
|
|
10
|
+
this.output = output;
|
|
11
|
+
}
|
|
12
|
+
start() {
|
|
13
|
+
if (this.started) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
this.started = true;
|
|
17
|
+
this.output.write(`Starting: ${this.title}\n\n`);
|
|
18
|
+
}
|
|
19
|
+
addStep(title) {
|
|
20
|
+
this.start();
|
|
21
|
+
this.stepCounter++;
|
|
22
|
+
const titleText = title;
|
|
23
|
+
this.output.write(`Step ${this.stepCounter}: ${titleText}... `);
|
|
24
|
+
const state = {
|
|
25
|
+
type: "step",
|
|
26
|
+
title,
|
|
27
|
+
phase: "running",
|
|
28
|
+
};
|
|
29
|
+
return new RunnableHandler(state, () => {
|
|
30
|
+
if (state.phase === "completed") {
|
|
31
|
+
this.output.write("completed\n");
|
|
32
|
+
}
|
|
33
|
+
else if (state.phase === "failed") {
|
|
34
|
+
this.output.write("FAILED\n");
|
|
35
|
+
if (state.error) {
|
|
36
|
+
this.output.write(` Error: ${state.error}\n`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (state.phase === "aborted") {
|
|
40
|
+
this.output.write("aborted\n");
|
|
41
|
+
}
|
|
42
|
+
if (state.progress) {
|
|
43
|
+
this.output.write(` Progress: ${state.progress}\n`);
|
|
44
|
+
}
|
|
45
|
+
if (state.output) {
|
|
46
|
+
const lines = state.output
|
|
47
|
+
.split("\n")
|
|
48
|
+
.filter((line) => line.trim());
|
|
49
|
+
this.output.write("got output:\n");
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
this.output.write(` ${line}\n`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async runStep(title, fn) {
|
|
57
|
+
const step = this.addStep(title);
|
|
58
|
+
try {
|
|
59
|
+
const promise = typeof fn === "function" ? fn() : fn;
|
|
60
|
+
const result = await promise;
|
|
61
|
+
step.complete();
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
step.error(err);
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
addInfo(title) {
|
|
70
|
+
this.start();
|
|
71
|
+
const titleText = title;
|
|
72
|
+
this.output.write(`Info: ${titleText}\n`);
|
|
73
|
+
}
|
|
74
|
+
async addConfirmation(question) {
|
|
75
|
+
this.start();
|
|
76
|
+
const questionText = question;
|
|
77
|
+
this.output.write(`Confirm: ${questionText}; automatically confirmed\n`);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
async addInput(question, mask) {
|
|
81
|
+
this.start();
|
|
82
|
+
const questionText = question;
|
|
83
|
+
const maskText = mask ? " (masked)" : "";
|
|
84
|
+
this.output.write(`Input: ${questionText}${maskText}; no input available\n`);
|
|
85
|
+
// For non-interactive use, throw an error
|
|
86
|
+
throw new Error("Interactive input not available in simple process renderer");
|
|
87
|
+
}
|
|
88
|
+
async addSelect(question, options) {
|
|
89
|
+
this.start();
|
|
90
|
+
const questionText = question;
|
|
91
|
+
this.output.write(`Selection: ${questionText}\n`);
|
|
92
|
+
this.output.write("Available options:\n");
|
|
93
|
+
options.forEach((option, index) => {
|
|
94
|
+
const labelText = option.label;
|
|
95
|
+
this.output.write(` ${index + 1}. ${labelText}\n`);
|
|
96
|
+
});
|
|
97
|
+
throw new Error("Interactive selection not available in simple process renderer");
|
|
98
|
+
}
|
|
99
|
+
addCleanup(title, fn) {
|
|
100
|
+
this.cleanupFns.push(fn);
|
|
101
|
+
}
|
|
102
|
+
async complete(summary) {
|
|
103
|
+
await this.cleanup();
|
|
104
|
+
const summaryText = this.renderElementToText(summary);
|
|
105
|
+
this.output.write("Completed: Process completed successfully\n\n");
|
|
106
|
+
this.output.write(`Summary: ${summaryText}\n`);
|
|
107
|
+
}
|
|
108
|
+
async error(err) {
|
|
109
|
+
await this.cleanup();
|
|
110
|
+
this.output.write(`ERROR: Process failed: ${err?.toString()}\n`);
|
|
111
|
+
}
|
|
112
|
+
async cleanup() {
|
|
113
|
+
if (this.cleanupFns.length === 0) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.output.write("Cleanup: Running cleanup tasks... ");
|
|
117
|
+
for (let i = 0; i < this.cleanupFns.length; i++) {
|
|
118
|
+
try {
|
|
119
|
+
await this.cleanupFns[i]();
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
this.output.write(`task ${i + 1} failed: ${err}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
this.output.write("completed\n");
|
|
126
|
+
}
|
|
127
|
+
renderElementToText(node) {
|
|
128
|
+
if (node === null || node === undefined) {
|
|
129
|
+
return "";
|
|
130
|
+
}
|
|
131
|
+
// Check if it's a React element with props.children
|
|
132
|
+
if (typeof node === "object" &&
|
|
133
|
+
"props" in node &&
|
|
134
|
+
node.props &&
|
|
135
|
+
typeof node.props === "object") {
|
|
136
|
+
const props = node.props;
|
|
137
|
+
if (props.children && typeof props.children === "string") {
|
|
138
|
+
return props.children;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return "[Complex content]";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|