@mittwald/cli 1.10.0 → 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/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/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/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/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
|
@@ -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 {};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { SimpleProcessRenderer } from "./process_simple.js";
|
|
2
|
+
import { describe, expect, it, jest, beforeEach, } from "@jest/globals";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Writable } from "stream";
|
|
5
|
+
describe("SimpleProcessRenderer", () => {
|
|
6
|
+
let output;
|
|
7
|
+
let testStream;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
output = "";
|
|
10
|
+
testStream = new Writable({
|
|
11
|
+
write(chunk, encoding, callback) {
|
|
12
|
+
output += chunk.toString();
|
|
13
|
+
if (callback)
|
|
14
|
+
callback();
|
|
15
|
+
return true;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
it("should start with a title", () => {
|
|
20
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
21
|
+
renderer.start();
|
|
22
|
+
expect(output).toContain("Starting: Test Process\n");
|
|
23
|
+
});
|
|
24
|
+
it("should display info messages", () => {
|
|
25
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
26
|
+
renderer.addInfo("This is an info message");
|
|
27
|
+
expect(output).toContain("Info: This is an info message\n");
|
|
28
|
+
});
|
|
29
|
+
it("should handle string step titles", () => {
|
|
30
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
31
|
+
const handler = renderer.addStep("Processing data");
|
|
32
|
+
expect(output).toContain("Step 1: Processing data... ");
|
|
33
|
+
handler.complete();
|
|
34
|
+
expect(output).toContain("completed\n");
|
|
35
|
+
});
|
|
36
|
+
it("should handle step failures", () => {
|
|
37
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
38
|
+
const handler = renderer.addStep("Failing step");
|
|
39
|
+
handler.error("Something went wrong");
|
|
40
|
+
expect(output).toContain("FAILED\n");
|
|
41
|
+
expect(output).toContain(" Error: Something went wrong\n");
|
|
42
|
+
});
|
|
43
|
+
it("should handle step progress", () => {
|
|
44
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
45
|
+
const handler = renderer.addStep("Long running task");
|
|
46
|
+
handler.progress("50% complete");
|
|
47
|
+
expect(output).toContain(" Progress: 50% complete\n");
|
|
48
|
+
});
|
|
49
|
+
it("should handle step output", () => {
|
|
50
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
51
|
+
const handler = renderer.addStep("Task with output");
|
|
52
|
+
handler.appendOutput("Line 1\nLine 2\n");
|
|
53
|
+
expect(output).toContain("got output:\n");
|
|
54
|
+
expect(output).toContain(" Line 1\n");
|
|
55
|
+
expect(output).toContain(" Line 2\n");
|
|
56
|
+
});
|
|
57
|
+
it("should run steps successfully", async () => {
|
|
58
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
59
|
+
const result = await renderer.runStep("Test step", async () => {
|
|
60
|
+
return "success";
|
|
61
|
+
});
|
|
62
|
+
expect(result).toBe("success");
|
|
63
|
+
expect(output).toContain("Step 1: Test step... ");
|
|
64
|
+
expect(output).toContain("completed\n");
|
|
65
|
+
});
|
|
66
|
+
it("should handle runStep failures", async () => {
|
|
67
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
68
|
+
await expect(renderer.runStep("Failing step", async () => {
|
|
69
|
+
throw new Error("Test error");
|
|
70
|
+
})).rejects.toThrow("Test error");
|
|
71
|
+
expect(output).toContain("FAILED\n");
|
|
72
|
+
});
|
|
73
|
+
it("should auto-confirm confirmations", async () => {
|
|
74
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
75
|
+
const result = await renderer.addConfirmation("Do you want to continue?");
|
|
76
|
+
expect(result).toBe(true);
|
|
77
|
+
expect(output).toContain("Confirm: Do you want to continue?; automatically confirmed\n");
|
|
78
|
+
});
|
|
79
|
+
it("should throw error for input requests", async () => {
|
|
80
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
81
|
+
await expect(renderer.addInput("Enter your name")).rejects.toThrow("Interactive input not available in simple process renderer");
|
|
82
|
+
});
|
|
83
|
+
it("should throw error for select requests", async () => {
|
|
84
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
85
|
+
await expect(renderer.addSelect("Choose option", [
|
|
86
|
+
{ value: "a", label: "Option A" },
|
|
87
|
+
{ value: "b", label: "Option B" },
|
|
88
|
+
])).rejects.toThrow("Interactive selection not available in simple process renderer");
|
|
89
|
+
});
|
|
90
|
+
it("should handle string titles", () => {
|
|
91
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
92
|
+
renderer.addStep("React step");
|
|
93
|
+
expect(output).toContain("Step 1: React step... ");
|
|
94
|
+
});
|
|
95
|
+
it("should complete with summary", async () => {
|
|
96
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
97
|
+
const summary = React.createElement("div", null, "Process completed!");
|
|
98
|
+
await renderer.complete(summary);
|
|
99
|
+
expect(output).toContain("Completed: Process completed successfully\n\n");
|
|
100
|
+
expect(output).toContain("Summary: Process completed!\n");
|
|
101
|
+
});
|
|
102
|
+
it("should handle errors", async () => {
|
|
103
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
104
|
+
await renderer.error("Something went wrong");
|
|
105
|
+
expect(output).toContain("ERROR: Process failed: Something went wrong\n");
|
|
106
|
+
});
|
|
107
|
+
it("should handle cleanup tasks", async () => {
|
|
108
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
109
|
+
const cleanupFn = jest.fn(async () => { });
|
|
110
|
+
renderer.addCleanup("Cleanup task", cleanupFn);
|
|
111
|
+
await renderer.complete(React.createElement("div", null, "Done"));
|
|
112
|
+
expect(cleanupFn).toHaveBeenCalled();
|
|
113
|
+
expect(output).toContain("Cleanup: Running cleanup tasks... ");
|
|
114
|
+
});
|
|
115
|
+
it("should render string titles", () => {
|
|
116
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
117
|
+
renderer.addStep("Hello from Text component");
|
|
118
|
+
expect(output).toContain("Step 1: Hello from Text component... ");
|
|
119
|
+
});
|
|
120
|
+
it("should render nested string content", () => {
|
|
121
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
122
|
+
renderer.addStep("Nested content");
|
|
123
|
+
expect(output).toContain("Step 1: Nested content... ");
|
|
124
|
+
});
|
|
125
|
+
it("should handle string content", () => {
|
|
126
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
127
|
+
renderer.addStep("First Second Third");
|
|
128
|
+
expect(output).toContain("Step 1: First Second Third... ");
|
|
129
|
+
});
|
|
130
|
+
it("should handle complex string content", () => {
|
|
131
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
132
|
+
renderer.addStep("String content 42 and React element");
|
|
133
|
+
expect(output).toContain("Step 1: String content 42 and React element... ");
|
|
134
|
+
});
|
|
135
|
+
it("should handle empty string content gracefully", () => {
|
|
136
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
137
|
+
renderer.addStep("");
|
|
138
|
+
expect(output).toContain("Step 1: ... ");
|
|
139
|
+
});
|
|
140
|
+
it("should handle different string content", () => {
|
|
141
|
+
const renderer = new SimpleProcessRenderer("Test Process", testStream);
|
|
142
|
+
renderer.addStep("true");
|
|
143
|
+
renderer.addStep("false");
|
|
144
|
+
renderer.addStep("123");
|
|
145
|
+
expect(output).toContain("Step 1: true... ");
|
|
146
|
+
expect(output).toContain("Step 2: false... ");
|
|
147
|
+
expect(output).toContain("Step 3: 123... ");
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import type { MittwaldAPIV2 } from "@mittwald/api-client";
|
|
3
|
+
type AppInstallation = MittwaldAPIV2.Components.Schemas.AppAppInstallation;
|
|
4
|
+
interface AppBackendAccessHintsProps {
|
|
5
|
+
appInstallation: AppInstallation;
|
|
6
|
+
backendPathTemplate: string;
|
|
7
|
+
appName: string;
|
|
8
|
+
appHost?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* AppBackendAccessHints displays backend/admin access information when a
|
|
12
|
+
* backendPathTemplate is available in the app version.
|
|
13
|
+
*/
|
|
14
|
+
export declare const AppBackendAccessHints: FC<AppBackendAccessHintsProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { Value } from "../Value.js";
|
|
4
|
+
const infoColor = "blueBright";
|
|
5
|
+
/**
|
|
6
|
+
* AppBackendAccessHints displays backend/admin access information when a
|
|
7
|
+
* backendPathTemplate is available in the app version.
|
|
8
|
+
*/
|
|
9
|
+
export const AppBackendAccessHints = ({ backendPathTemplate, appName, appHost, }) => {
|
|
10
|
+
return (_jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, color: infoColor, children: "\uD83D\uDD27 Backend Access:" }), _jsx(Text, { color: "gray", children: appHost
|
|
11
|
+
? `Your ${appName} backend is available at:`
|
|
12
|
+
: `Once you connect a domain, your ${appName} backend will be available at:` }), _jsx(Text, { color: "gray", children: _jsx(Value, { children: backendPathTemplate.replace("{domain}", appHost ?? "<your-domain>") }) })] }));
|
|
13
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import type { MittwaldAPIV2 } from "@mittwald/api-client";
|
|
3
|
+
type AppInstallation = MittwaldAPIV2.Components.Schemas.AppAppInstallation;
|
|
4
|
+
interface AppDomainConnectionHintsProps {
|
|
5
|
+
appInstallation: AppInstallation;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* AppDomainConnectionHints displays instructions for connecting a domain to an
|
|
9
|
+
* app installation via virtualhost creation.
|
|
10
|
+
*/
|
|
11
|
+
export declare const AppDomainConnectionHints: FC<AppDomainConnectionHintsProps>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from "ink";
|
|
3
|
+
import { Value } from "../Value.js";
|
|
4
|
+
import { CommandHint } from "../Container/CommandHint.js";
|
|
5
|
+
const infoColor = "blueBright";
|
|
6
|
+
/**
|
|
7
|
+
* AppDomainConnectionHints displays instructions for connecting a domain to an
|
|
8
|
+
* app installation via virtualhost creation.
|
|
9
|
+
*/
|
|
10
|
+
export const AppDomainConnectionHints = ({ appInstallation, }) => {
|
|
11
|
+
return (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, color: infoColor, children: "\uD83C\uDF10 Connect via Domain:" }), _jsx(CommandHint, { command: [
|
|
12
|
+
"mw",
|
|
13
|
+
"domain",
|
|
14
|
+
"virtualhost",
|
|
15
|
+
"create",
|
|
16
|
+
"--hostname",
|
|
17
|
+
"<your-domain.com>",
|
|
18
|
+
"--path-to-installation",
|
|
19
|
+
`/:${appInstallation.id}`,
|
|
20
|
+
], description: _jsxs(_Fragment, { children: ["Connect ", _jsx(Value, { children: "<your-domain.com>" }), " to your app installation, making it accessible via HTTPS. This is required for external access to your application."] }) })] }));
|
|
21
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import type { MittwaldAPIV2 } from "@mittwald/api-client";
|
|
3
|
+
type AppInstallation = MittwaldAPIV2.Components.Schemas.AppAppInstallation;
|
|
4
|
+
interface AppManagementCommandsProps {
|
|
5
|
+
appInstallation: AppInstallation;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* AppManagementCommands displays management commands for app installations
|
|
9
|
+
* including SSH access, file operations, and maintenance tasks.
|
|
10
|
+
*/
|
|
11
|
+
export declare const AppManagementCommands: FC<AppManagementCommandsProps>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from "ink";
|
|
3
|
+
import { CommandHint } from "../Container/CommandHint.js";
|
|
4
|
+
const infoColor = "blueBright";
|
|
5
|
+
/**
|
|
6
|
+
* AppManagementCommands displays management commands for app installations
|
|
7
|
+
* including SSH access, file operations, and maintenance tasks.
|
|
8
|
+
*/
|
|
9
|
+
export const AppManagementCommands = ({ appInstallation, }) => {
|
|
10
|
+
return (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, color: infoColor, children: "\uD83D\uDD27 Manage your application:" }), _jsx(CommandHint, { command: ["mw", "app", "ssh", appInstallation.shortId], description: "Open SSH session to your app installation" }), _jsx(CommandHint, { command: ["mw", "app", "download", appInstallation.shortId], description: "Download app files to your local machine" }), _jsx(CommandHint, { command: [
|
|
11
|
+
"mw",
|
|
12
|
+
"app",
|
|
13
|
+
"upload",
|
|
14
|
+
appInstallation.shortId,
|
|
15
|
+
"<local-file>",
|
|
16
|
+
], description: "Upload files from your local machine to the app" }), _jsx(CommandHint, { command: ["mw", "app", "get", appInstallation.shortId], description: "Show detailed information about your app installation" })] }));
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import type { MittwaldAPIV2 } from "@mittwald/api-client";
|
|
3
|
+
type AppInstallation = MittwaldAPIV2.Components.Schemas.AppAppInstallation;
|
|
4
|
+
type AppVersion = MittwaldAPIV2.Components.Schemas.AppAppVersion;
|
|
5
|
+
interface AppUsageHintsProps {
|
|
6
|
+
appInstallation: AppInstallation;
|
|
7
|
+
appVersion: AppVersion;
|
|
8
|
+
appName: string;
|
|
9
|
+
appHost?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* AppUsageHints displays comprehensive usage instructions for app
|
|
13
|
+
* installations, including domain connection setup and backend access
|
|
14
|
+
* information.
|
|
15
|
+
*/
|
|
16
|
+
declare const AppUsageHints: FC<AppUsageHintsProps>;
|
|
17
|
+
export default AppUsageHints;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { Value } from "../Value.js";
|
|
4
|
+
import useDefaultBoxStyles from "../../styles/useDefaultBoxStyles.js";
|
|
5
|
+
import { AppDomainConnectionHints } from "./AppDomainConnectionHints.js";
|
|
6
|
+
import { AppBackendAccessHints } from "./AppBackendAccessHints.js";
|
|
7
|
+
import { AppManagementCommands } from "./AppManagementCommands.js";
|
|
8
|
+
const infoColor = "blueBright";
|
|
9
|
+
/**
|
|
10
|
+
* AppUsageHints displays comprehensive usage instructions for app
|
|
11
|
+
* installations, including domain connection setup and backend access
|
|
12
|
+
* information.
|
|
13
|
+
*/
|
|
14
|
+
const AppUsageHints = ({ appInstallation, appVersion, appName, appHost, }) => {
|
|
15
|
+
const defaultBoxStyles = useDefaultBoxStyles();
|
|
16
|
+
const boxProps = {
|
|
17
|
+
...defaultBoxStyles,
|
|
18
|
+
borderColor: infoColor,
|
|
19
|
+
marginLeft: 2,
|
|
20
|
+
};
|
|
21
|
+
return (_jsxs(Box, { ...boxProps, flexDirection: "column", children: [_jsx(Text, { bold: true, underline: true, color: infoColor, children: "USAGE HINTS" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Connect to your application using these methods:" }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(AppDomainConnectionHints, { appInstallation: appInstallation }), appVersion.backendPathTemplate && (_jsx(AppBackendAccessHints, { appInstallation: appInstallation, backendPathTemplate: appVersion.backendPathTemplate, appName: appName, appHost: appHost })), _jsx(AppManagementCommands, { appInstallation: appInstallation }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: infoColor, children: ["\uD83D\uDCA1 Tip: Use ", _jsx(Value, { children: "mw app list" }), " to see all your app installations and their current status."] }) })] })] }));
|
|
22
|
+
};
|
|
23
|
+
export default AppUsageHints;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FC, ReactNode } from "react";
|
|
2
|
+
export interface CommandHintProps {
|
|
3
|
+
command: string[];
|
|
4
|
+
description: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* CommandHint is a functional React component that renders a command hint
|
|
8
|
+
* display. It presents a styled command and its corresponding description.
|
|
9
|
+
*
|
|
10
|
+
* @param command An array of strings representing the command to be displayed.
|
|
11
|
+
* @param description A textual description of the command.
|
|
12
|
+
* @returns A JSX element displaying the command and description.
|
|
13
|
+
*/
|
|
14
|
+
export declare const CommandHint: FC<CommandHintProps>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
/**
|
|
4
|
+
* CommandHint is a functional React component that renders a command hint
|
|
5
|
+
* display. It presents a styled command and its corresponding description.
|
|
6
|
+
*
|
|
7
|
+
* @param command An array of strings representing the command to be displayed.
|
|
8
|
+
* @param description A textual description of the command.
|
|
9
|
+
* @returns A JSX element displaying the command and description.
|
|
10
|
+
*/
|
|
11
|
+
export const CommandHint = ({ command, description }) => {
|
|
12
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { children: _jsx(Text, { color: "yellow", children: command.join(" ") }) }), _jsx(Box, { marginLeft: 2, marginBottom: 1, children: _jsx(Text, { wrap: "wrap", children: description }) })] }));
|
|
13
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
interface ContainerManagementCommandsProps {
|
|
3
|
+
containerIdentifier: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* ContainerManagementCommands is a React functional component that provides
|
|
7
|
+
* commands and instructions for interacting with a specific container.
|
|
8
|
+
*
|
|
9
|
+
* This component displays a set of command hints, allowing users to:
|
|
10
|
+
*
|
|
11
|
+
* - Connect to a container via SSH.
|
|
12
|
+
* - View logs generated by the container.
|
|
13
|
+
* - Execute specific commands within the container.
|
|
14
|
+
*
|
|
15
|
+
* The displayed commands are dynamically generated based on the
|
|
16
|
+
* `containerIdentifier` prop, which identifies the container to manage.
|
|
17
|
+
*
|
|
18
|
+
* @property string ContainerIdentifier - The unique identifier of the container
|
|
19
|
+
* to manage. This is included in the commands displayed by the component.
|
|
20
|
+
*/
|
|
21
|
+
export declare const ContainerManagementCommands: FC<ContainerManagementCommandsProps>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { CommandHint } from "./CommandHint.js";
|
|
4
|
+
const infoColor = "blueBright";
|
|
5
|
+
/**
|
|
6
|
+
* ContainerManagementCommands is a React functional component that provides
|
|
7
|
+
* commands and instructions for interacting with a specific container.
|
|
8
|
+
*
|
|
9
|
+
* This component displays a set of command hints, allowing users to:
|
|
10
|
+
*
|
|
11
|
+
* - Connect to a container via SSH.
|
|
12
|
+
* - View logs generated by the container.
|
|
13
|
+
* - Execute specific commands within the container.
|
|
14
|
+
*
|
|
15
|
+
* The displayed commands are dynamically generated based on the
|
|
16
|
+
* `containerIdentifier` prop, which identifies the container to manage.
|
|
17
|
+
*
|
|
18
|
+
* @property string ContainerIdentifier - The unique identifier of the container
|
|
19
|
+
* to manage. This is included in the commands displayed by the component.
|
|
20
|
+
*/
|
|
21
|
+
export const ContainerManagementCommands = ({ containerIdentifier }) => {
|
|
22
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: infoColor, children: "\uD83D\uDD27 Manage Your Container:" }) }), _jsx(CommandHint, { command: ["mw", "container", "ssh", containerIdentifier], description: "Connect to the container via SSH to run commands interactively" }), _jsx(CommandHint, { command: ["mw", "container", "logs", containerIdentifier], description: "View the container's log output and monitor its activity" }), _jsx(CommandHint, { command: ["mw", "container", "exec", containerIdentifier, "<command>"], description: "Execute a specific command inside the running container" })] }));
|
|
23
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import type { MittwaldAPIV2 } from "@mittwald/api-client";
|
|
3
|
+
type ContainerServiceResponse = MittwaldAPIV2.Components.Schemas.ContainerServiceResponse;
|
|
4
|
+
interface ContainerUsageHintsProps {
|
|
5
|
+
service: ContainerServiceResponse;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* ContainerUsageHints displays comprehensive usage instructions for containers,
|
|
9
|
+
* adapting the content based on whether the container exposes ports or not.
|
|
10
|
+
*/
|
|
11
|
+
declare const ContainerUsageHints: FC<ContainerUsageHintsProps>;
|
|
12
|
+
export default ContainerUsageHints;
|