@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.
Files changed (110) hide show
  1. package/bin/run.js +4 -1
  2. package/dist/commands/app/create/node.d.ts +1 -3
  3. package/dist/commands/app/create/php-worker.d.ts +1 -3
  4. package/dist/commands/app/create/php.d.ts +1 -3
  5. package/dist/commands/app/create/python.d.ts +1 -3
  6. package/dist/commands/app/create/static.d.ts +1 -3
  7. package/dist/commands/app/dependency/update.js +2 -4
  8. package/dist/commands/app/download.js +2 -2
  9. package/dist/commands/app/exec.d.ts +17 -0
  10. package/dist/commands/app/exec.js +71 -0
  11. package/dist/commands/app/install/contao.d.ts +1 -3
  12. package/dist/commands/app/install/joomla.d.ts +1 -3
  13. package/dist/commands/app/install/matomo.d.ts +1 -3
  14. package/dist/commands/app/install/nextcloud.d.ts +1 -3
  15. package/dist/commands/app/install/shopware5.d.ts +1 -3
  16. package/dist/commands/app/install/shopware6.d.ts +1 -3
  17. package/dist/commands/app/install/typo3.d.ts +1 -3
  18. package/dist/commands/app/install/wordpress.d.ts +1 -3
  19. package/dist/commands/app/ssh.d.ts +1 -0
  20. package/dist/commands/app/ssh.js +15 -1
  21. package/dist/commands/app/update.js +4 -8
  22. package/dist/commands/app/upgrade.js +9 -9
  23. package/dist/commands/backup/create.js +1 -2
  24. package/dist/commands/backup/download.js +4 -5
  25. package/dist/commands/container/exec.d.ts +1 -7
  26. package/dist/commands/container/exec.js +11 -22
  27. package/dist/commands/container/run.d.ts +4 -2
  28. package/dist/commands/container/run.js +7 -6
  29. package/dist/commands/database/mysql/create.js +1 -2
  30. package/dist/commands/database/mysql/dump.js +1 -2
  31. package/dist/commands/database/mysql/import.js +1 -2
  32. package/dist/commands/ddev/init.js +2 -6
  33. package/dist/commands/extension/install.js +1 -3
  34. package/dist/commands/login/reset.js +1 -2
  35. package/dist/commands/mail/address/create.js +1 -4
  36. package/dist/commands/mail/deliverybox/create.js +1 -4
  37. package/dist/commands/project/create.js +4 -6
  38. package/dist/commands/registry/create.js +1 -2
  39. package/dist/commands/registry/update.js +1 -2
  40. package/dist/commands/user/api-token/create.js +1 -1
  41. package/dist/commands/user/ssh-key/create.js +3 -8
  42. package/dist/commands/user/ssh-key/import.js +2 -3
  43. package/dist/hooks/prerun/update-brew-check.js +1 -1
  44. package/dist/lib/basecommands/DeleteBaseCommand.js +4 -4
  45. package/dist/lib/ddev/init_assert.js +1 -6
  46. package/dist/lib/ddev/init_database.js +1 -7
  47. package/dist/lib/ddev/init_projecttype.js +2 -11
  48. package/dist/lib/intellij/config.d.ts +5 -0
  49. package/dist/lib/intellij/config.js +295 -0
  50. package/dist/lib/intellij/config.test.d.ts +1 -0
  51. package/dist/lib/intellij/config.test.js +262 -0
  52. package/dist/lib/intellij/config_xml_types.d.ts +72 -0
  53. package/dist/lib/intellij/config_xml_types.js +2 -0
  54. package/dist/lib/resources/app/Installer.d.ts +6 -2
  55. package/dist/lib/resources/app/Installer.js +13 -6
  56. package/dist/lib/resources/app/flags.js +9 -12
  57. package/dist/lib/resources/app/install.d.ts +2 -1
  58. package/dist/lib/resources/app/install.js +3 -1
  59. package/dist/lib/resources/app/versions.js +1 -4
  60. package/dist/lib/resources/app/wait.js +1 -3
  61. package/dist/lib/resources/mail/commons.js +1 -4
  62. package/dist/lib/resources/ssh/appinstall.d.ts +3 -1
  63. package/dist/lib/resources/ssh/appinstall.js +1 -0
  64. package/dist/lib/resources/ssh/environment.d.ts +7 -0
  65. package/dist/lib/resources/ssh/environment.js +21 -0
  66. package/dist/rendering/process/components/ProcessStateIcon.js +1 -1
  67. package/dist/rendering/process/process.d.ts +16 -16
  68. package/dist/rendering/process/process_exec.d.ts +1 -2
  69. package/dist/rendering/process/process_fancy.d.ts +9 -9
  70. package/dist/rendering/process/process_flags.js +4 -0
  71. package/dist/rendering/process/process_quiet.d.ts +3 -4
  72. package/dist/rendering/process/process_simple.d.ts +26 -0
  73. package/dist/rendering/process/process_simple.js +143 -0
  74. package/dist/rendering/process/process_simple.test.d.ts +1 -0
  75. package/dist/rendering/process/process_simple.test.js +149 -0
  76. package/dist/rendering/react/components/AppInstallation/AppBackendAccessHints.d.ts +15 -0
  77. package/dist/rendering/react/components/AppInstallation/AppBackendAccessHints.js +13 -0
  78. package/dist/rendering/react/components/AppInstallation/AppDomainConnectionHints.d.ts +12 -0
  79. package/dist/rendering/react/components/AppInstallation/AppDomainConnectionHints.js +21 -0
  80. package/dist/rendering/react/components/AppInstallation/AppManagementCommands.d.ts +12 -0
  81. package/dist/rendering/react/components/AppInstallation/AppManagementCommands.js +17 -0
  82. package/dist/rendering/react/components/AppInstallation/AppUsageHints.d.ts +17 -0
  83. package/dist/rendering/react/components/AppInstallation/AppUsageHints.js +23 -0
  84. package/dist/rendering/react/components/Container/CommandHint.d.ts +14 -0
  85. package/dist/rendering/react/components/Container/CommandHint.js +13 -0
  86. package/dist/rendering/react/components/Container/ContainerManagementCommands.d.ts +22 -0
  87. package/dist/rendering/react/components/Container/ContainerManagementCommands.js +23 -0
  88. package/dist/rendering/react/components/Container/ContainerUsageHints.d.ts +12 -0
  89. package/dist/rendering/react/components/Container/ContainerUsageHints.js +35 -0
  90. package/dist/rendering/react/components/Container/DomainConnectionHints.d.ts +12 -0
  91. package/dist/rendering/react/components/Container/DomainConnectionHints.js +21 -0
  92. package/dist/rendering/react/components/Container/InternalConnectionHints.d.ts +12 -0
  93. package/dist/rendering/react/components/Container/InternalConnectionHints.js +12 -0
  94. package/dist/rendering/react/components/Container/NoPortsUsageHints.d.ts +12 -0
  95. package/dist/rendering/react/components/Container/NoPortsUsageHints.js +12 -0
  96. package/dist/rendering/react/components/Container/PortConnectionHints.d.ts +13 -0
  97. package/dist/rendering/react/components/Container/PortConnectionHints.js +11 -0
  98. package/dist/rendering/react/components/Container/PortForwardingHints.d.ts +12 -0
  99. package/dist/rendering/react/components/Container/PortForwardingHints.js +18 -0
  100. package/dist/rendering/react/components/Container/types.d.ts +4 -0
  101. package/dist/rendering/react/components/Container/types.js +1 -0
  102. package/dist/rendering/react/components/Error/ErrorBox.d.ts +1 -1
  103. package/dist/rendering/react/components/Error/ErrorBox.js +3 -4
  104. package/dist/rendering/react/components/Error/GenericError.js +1 -1
  105. package/dist/rendering/react/components/ErrorBoundary.d.ts +1 -1
  106. package/dist/rendering/react/components/Success.d.ts +0 -1
  107. package/dist/rendering/react/components/Success.js +4 -2
  108. package/dist/rendering/react/styles/useDefaultBoxStyles.d.ts +11 -0
  109. package/dist/rendering/react/styles/useDefaultBoxStyles.js +23 -0
  110. package/package.json +6 -5
package/bin/run.js CHANGED
@@ -5,5 +5,8 @@ import handleError from "../dist/lib/error/handleError.js";
5
5
 
6
6
  oclif
7
7
  .run(process.argv.slice(2), import.meta.url)
8
- .then(oclif.flush)
8
+ .then(async () => {
9
+ await oclif.flush();
10
+ process.exit(0);
11
+ })
9
12
  .catch(handleError);
@@ -5,8 +5,6 @@ export declare const nodeInstaller: AppInstaller<"site-title" | "entrypoint">;
5
5
  export default class InstallNode extends ExecRenderBaseCommand<typeof InstallNode, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("entrypoint" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -5,8 +5,6 @@ export declare const phpWorkerInstaller: AppInstaller<"site-title" | "entrypoint
5
5
  export default class InstallPhpWorker extends ExecRenderBaseCommand<typeof InstallPhpWorker, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("entrypoint" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -5,8 +5,6 @@ export declare const phpInstaller: AppInstaller<"site-title" | "document-root">;
5
5
  export default class InstallPhp extends ExecRenderBaseCommand<typeof InstallPhp, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("document-root" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -5,8 +5,6 @@ export declare const pythonInstaller: AppInstaller<"site-title" | "entrypoint">;
5
5
  export default class InstallPython extends ExecRenderBaseCommand<typeof InstallPython, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("entrypoint" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -5,8 +5,6 @@ export declare const staticInstaller: AppInstaller<"site-title" | "document-root
5
5
  export default class InstallStatic extends ExecRenderBaseCommand<typeof InstallStatic, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("document-root" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { ExecRenderBaseCommand } from "../../../lib/basecommands/ExecRenderBaseCommand.js";
3
3
  import { appInstallationArgs } from "../../../lib/resources/app/flags.js";
4
4
  import { makeProcessRenderer, processFlags, } from "../../../rendering/process/process_flags.js";
@@ -6,8 +6,6 @@ import { Flags } from "@oclif/core";
6
6
  import { assertStatus } from "@mittwald/api-client-commons";
7
7
  import { Success } from "../../../rendering/react/components/Success.js";
8
8
  import { Range, SemVer } from "semver";
9
- import { Value } from "../../../rendering/react/components/Value.js";
10
- import { Text } from "ink";
11
9
  export default class Update extends ExecRenderBaseCommand {
12
10
  static summary = "Update the dependencies of an app";
13
11
  static args = { ...appInstallationArgs };
@@ -69,7 +67,7 @@ export default class Update extends ExecRenderBaseCommand {
69
67
  }
70
68
  return versions[versions.length - 1];
71
69
  });
72
- process.addInfo(_jsxs(Text, { children: ["selected ", _jsx(Value, { children: systemSoftware.name }), " version:", " ", _jsx(Value, { children: version.externalVersion })] }));
70
+ process.addInfo(`selected ${systemSoftware.name} version: ${version.externalVersion}`);
73
71
  versionsToUpdate[systemSoftware.id] = {
74
72
  systemSoftwareVersion: version.id,
75
73
  updatePolicy,
@@ -33,11 +33,11 @@ export class Download extends ExecRenderBaseCommand {
33
33
  static examples = [
34
34
  {
35
35
  description: "Download entire app to current working directory",
36
- command: "$ <%= config.bin %> <%= command.id %> .",
36
+ command: "$ <%= config.bin %> <%= command.id %> --target .",
37
37
  },
38
38
  {
39
39
  description: "Download only shared dir from a deployer-managed app",
40
- command: "<%= config.bin %> <%= command.id %> --remote-sub-directory=shared .",
40
+ command: "<%= config.bin %> <%= command.id %> --remote-sub-directory=shared --target .",
41
41
  },
42
42
  ];
43
43
  async exec() {
@@ -0,0 +1,17 @@
1
+ import { ExtendedBaseCommand } from "../../lib/basecommands/ExtendedBaseCommand.js";
2
+ export default class Exec extends ExtendedBaseCommand<typeof Exec> {
3
+ static summary: string;
4
+ static description: string;
5
+ static args: {
6
+ command: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ env: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ "installation-id": import("@oclif/core/interfaces").OptionFlag<string>;
13
+ "ssh-user": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ "ssh-identity-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,71 @@
1
+ import * as child_process from "child_process";
2
+ import { Args, Flags } from "@oclif/core";
3
+ import { ExtendedBaseCommand } from "../../lib/basecommands/ExtendedBaseCommand.js";
4
+ import { sshConnectionFlags } from "../../lib/resources/ssh/flags.js";
5
+ import { sshUsageDocumentation } from "../../lib/resources/ssh/doc.js";
6
+ import { buildSSHClientFlags } from "../../lib/resources/ssh/connection.js";
7
+ import { appInstallationFlags } from "../../lib/resources/app/flags.js";
8
+ import { getSSHConnectionForAppInstallation } from "../../lib/resources/ssh/appinstall.js";
9
+ import shellEscape from "shell-escape";
10
+ import { prepareEnvironmentVariables } from "../../lib/resources/ssh/environment.js";
11
+ export default class Exec extends ExtendedBaseCommand {
12
+ static summary = "Execute a command in an app installation via SSH non-interactively.";
13
+ static description = sshUsageDocumentation;
14
+ static args = {
15
+ command: Args.string({
16
+ description: "Command to execute in the app installation",
17
+ required: true,
18
+ }),
19
+ };
20
+ static flags = {
21
+ ...sshConnectionFlags,
22
+ ...appInstallationFlags,
23
+ workdir: Flags.string({
24
+ char: "w",
25
+ summary: "working directory where the command will be executed",
26
+ default: undefined,
27
+ }),
28
+ env: Flags.string({
29
+ char: "e",
30
+ summary: "environment variables to set for the command (format: KEY=VALUE)",
31
+ multiple: true,
32
+ multipleNonGreedy: true,
33
+ }),
34
+ quiet: Flags.boolean({
35
+ char: "q",
36
+ summary: "disable informational output, only show command results",
37
+ default: false,
38
+ }),
39
+ };
40
+ async run() {
41
+ const { args, flags } = await this.parse(Exec);
42
+ const appInstallationId = await this.withAppInstallationId(Exec);
43
+ const { host, user, directory } = await getSSHConnectionForAppInstallation(this.apiClient, appInstallationId, flags["ssh-user"]);
44
+ if (!flags.quiet) {
45
+ this.log("executing command on %s as %s", host, user);
46
+ }
47
+ const command = args.command;
48
+ const workdir = flags.workdir ?? directory;
49
+ // Build the command to execute
50
+ let execCommand = "";
51
+ // Add environment variables if provided
52
+ if (flags.env && flags.env.length > 0) {
53
+ execCommand += prepareEnvironmentVariables(flags.env);
54
+ }
55
+ // Change to working directory if specified, otherwise use app directory
56
+ execCommand += `cd ${shellEscape([workdir])} && `;
57
+ // Add the actual command
58
+ execCommand += command;
59
+ const sshArgs = buildSSHClientFlags(user, host, flags, {
60
+ interactive: false,
61
+ });
62
+ const wrappedExecCommand = shellEscape(["/bin/bash", "-c", execCommand]);
63
+ this.debug("running ssh %o, with command %o", sshArgs, wrappedExecCommand);
64
+ const result = child_process.spawnSync("/usr/bin/ssh", [...sshArgs, wrappedExecCommand], {
65
+ stdio: "inherit",
66
+ });
67
+ if (result.status !== 0) {
68
+ this.error(`Command failed with exit code ${result.status}`);
69
+ }
70
+ }
71
+ }
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
4
4
  export default class InstallContao extends ExecRenderBaseCommand<typeof InstallContao, AppInstallationResult> {
5
5
  static description: string;
6
6
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | ("wait" | "wait-timeout" | "site-title"))[]>>;
7
- protected exec(): Promise<{
8
- appInstallationId: string;
9
- }>;
7
+ protected exec(): Promise<AppInstallationResult>;
10
8
  protected render(result: AppInstallationResult): React.ReactNode;
11
9
  }
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
4
4
  export default class InstallJoomla extends ExecRenderBaseCommand<typeof InstallJoomla, AppInstallationResult> {
5
5
  static description: string;
6
6
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | ("wait" | "wait-timeout" | "site-title"))[]>>;
7
- protected exec(): Promise<{
8
- appInstallationId: string;
9
- }>;
7
+ protected exec(): Promise<AppInstallationResult>;
10
8
  protected render(result: AppInstallationResult): React.ReactNode;
11
9
  }
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
4
4
  export default class InstallMatomo extends ExecRenderBaseCommand<typeof InstallMatomo, AppInstallationResult> {
5
5
  static description: string;
6
6
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | ("wait" | "wait-timeout" | "site-title"))[]>>;
7
- protected exec(): Promise<{
8
- appInstallationId: string;
9
- }>;
7
+ protected exec(): Promise<AppInstallationResult>;
10
8
  protected render(result: AppInstallationResult): React.ReactNode;
11
9
  }
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
4
4
  export default class InstallNextcloud extends ExecRenderBaseCommand<typeof InstallNextcloud, AppInstallationResult> {
5
5
  static description: string;
6
6
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | ("wait" | "wait-timeout" | "site-title"))[]>>;
7
- protected exec(): Promise<{
8
- appInstallationId: string;
9
- }>;
7
+ protected exec(): Promise<AppInstallationResult>;
10
8
  protected render(result: AppInstallationResult): React.ReactNode;
11
9
  }
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
4
4
  export default class InstallShopware5 extends ExecRenderBaseCommand<typeof InstallShopware5, AppInstallationResult> {
5
5
  static description: string;
6
6
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | "shop-email" | "shop-lang" | "shop-currency" | ("wait" | "wait-timeout" | "site-title"))[]>>;
7
- protected exec(): Promise<{
8
- appInstallationId: string;
9
- }>;
7
+ protected exec(): Promise<AppInstallationResult>;
10
8
  protected render(result: AppInstallationResult): React.ReactNode;
11
9
  }
@@ -5,8 +5,6 @@ export declare const shopware6Installer: AppInstaller<"version" | "host" | "admi
5
5
  export default class InstallShopware6 extends ExecRenderBaseCommand<typeof InstallShopware6, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | "shop-email" | "shop-lang" | "shop-currency" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -5,8 +5,6 @@ export declare const typo3Installer: AppInstaller<"version" | "host" | "admin-us
5
5
  export default class InstallTYPO3 extends ExecRenderBaseCommand<typeof InstallTYPO3, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "install-mode" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -5,8 +5,6 @@ export declare const wordpressInstaller: AppInstaller<"version" | "host" | "admi
5
5
  export default class InstallWordPress extends ExecRenderBaseCommand<typeof InstallWordPress, AppInstallationResult> {
6
6
  static description: string;
7
7
  static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | ("wait" | "wait-timeout" | "site-title"))[]>>;
8
- protected exec(): Promise<{
9
- appInstallationId: string;
10
- }>;
8
+ protected exec(): Promise<AppInstallationResult>;
11
9
  protected render(result: AppInstallationResult): React.ReactNode;
12
10
  }
@@ -9,6 +9,7 @@ export default class Ssh extends ExtendedBaseCommand<typeof Ssh> {
9
9
  cd: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
10
  info: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
11
  test: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ "generate-intellij-config": import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
13
  "ssh-user": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
14
  "ssh-identity-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
15
  };
@@ -6,6 +6,7 @@ import { getSSHConnectionForAppInstallation } from "../../lib/resources/ssh/appi
6
6
  import { sshConnectionFlags, } from "../../lib/resources/ssh/flags.js";
7
7
  import { sshWrapperDocumentation } from "../../lib/resources/ssh/doc.js";
8
8
  import { buildSSHClientFlags } from "../../lib/resources/ssh/connection.js";
9
+ import { generateIntellijConfigs } from "../../lib/intellij/config.js";
9
10
  export default class Ssh extends ExtendedBaseCommand {
10
11
  static summary = "Connect to an app via SSH";
11
12
  static description = "Establishes an interactive SSH connection to an app installation.\n\n" +
@@ -24,11 +25,24 @@ export default class Ssh extends ExtendedBaseCommand {
24
25
  test: Flags.boolean({
25
26
  summary: "test connection and exit",
26
27
  }),
28
+ "generate-intellij-config": Flags.boolean({
29
+ summary: "generate IntelliJ IDEA SSH and deployment configuration files",
30
+ }),
27
31
  };
28
32
  async run() {
29
33
  const { flags } = await this.parse(Ssh);
30
34
  const appInstallationId = await this.withAppInstallationId(Ssh);
31
- const { host, user, directory } = await getSSHConnectionForAppInstallation(this.apiClient, appInstallationId, flags["ssh-user"]);
35
+ const { host, user, directory, appShortId } = await getSSHConnectionForAppInstallation(this.apiClient, appInstallationId, flags["ssh-user"]);
36
+ if (flags["generate-intellij-config"]) {
37
+ generateIntellijConfigs({
38
+ host,
39
+ user,
40
+ directory,
41
+ appShortId,
42
+ });
43
+ this.log("IntelliJ IDEA configuration files generated in .idea/ directory");
44
+ return;
45
+ }
32
46
  if (flags.info) {
33
47
  this.log("hostname: %o", host);
34
48
  this.log("username: %o", user);
@@ -1,9 +1,8 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
3
3
  import { appInstallationArgs, withAppInstallationId, } from "../../lib/resources/app/flags.js";
4
4
  import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
5
5
  import { Success } from "../../rendering/react/components/Success.js";
6
- import { Value } from "../../rendering/react/components/Value.js";
7
6
  import { Flags } from "@oclif/core";
8
7
  export class Update extends ExecRenderBaseCommand {
9
8
  static summary = "Update properties of an app installation (use 'upgrade' to update the app version)";
@@ -56,7 +55,7 @@ function buildUpdateBodyFromFlags(flags) {
56
55
  const updateBody = {};
57
56
  const info = [];
58
57
  if (flags.entrypoint) {
59
- info.push(_jsx(UpdateFieldInfo, { name: "entrypoint", value: flags.entrypoint }));
58
+ info.push(`setting entrypoint to ${flags.entrypoint}`);
60
59
  updateBody.userInputs = [
61
60
  ...(updateBody.userInputs || []),
62
61
  {
@@ -66,15 +65,12 @@ function buildUpdateBodyFromFlags(flags) {
66
65
  ];
67
66
  }
68
67
  if (flags["document-root"]) {
69
- info.push(_jsx(UpdateFieldInfo, { name: "document root", value: flags["document-root"] }));
68
+ info.push(`setting document root to ${flags["document-root"]}`);
70
69
  updateBody.customDocumentRoot = flags["document-root"];
71
70
  }
72
71
  if (flags.description !== undefined) {
73
- info.push(_jsx(UpdateFieldInfo, { name: "description", value: flags.description }));
72
+ info.push(`setting description to ${flags.description}`);
74
73
  updateBody.description = flags.description;
75
74
  }
76
75
  return [updateBody, info];
77
76
  }
78
- function UpdateFieldInfo({ name, value }) {
79
- return (_jsxs(_Fragment, { children: ["setting ", name, " to ", _jsx(Value, { children: value })] }));
80
- }
@@ -1,4 +1,4 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsxs as _jsxs, Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
3
3
  import { appInstallationArgs, withAppInstallationId, } from "../../lib/resources/app/flags.js";
4
4
  import { projectFlags } from "../../lib/resources/project/flags.js";
@@ -51,15 +51,15 @@ export class UpgradeApp extends ExecRenderBaseCommand {
51
51
  ux.exit(1);
52
52
  }
53
53
  if (!this.flags.force) {
54
- const confirmed = await process.addConfirmation(_jsxs(Text, { children: ["Confirm upgrading ", currentApp.name, " ", currentAppVersion.externalVersion, " (", currentAppInstallation.description, ") to version", " ", targetAppVersion.externalVersion] }));
54
+ const confirmed = await process.addConfirmation(`Confirm upgrading ${currentApp.name} ${currentAppVersion.externalVersion} (${currentAppInstallation.description}) to version ${targetAppVersion.externalVersion}`);
55
55
  if (!confirmed) {
56
- process.addInfo(_jsx(Text, { children: "Upgrade will not be triggered." }));
56
+ process.addInfo("Upgrade will not be triggered.");
57
57
  process.complete(_jsx(_Fragment, {}));
58
58
  ux.exit(1);
59
59
  }
60
60
  }
61
61
  else {
62
- process.addInfo(_jsxs(Text, { children: ["Commencing upgrade of ", currentApp.name, " ", currentAppVersion.externalVersion, " (", currentAppInstallation.description, ") to Version", " ", targetAppVersion.externalVersion, "."] }));
62
+ process.addInfo(`Commencing upgrade of ${currentApp.name} ${currentAppVersion.externalVersion} (${currentAppInstallation.description}) to Version ${targetAppVersion.externalVersion}.`);
63
63
  }
64
64
  const appUpgradePayload = {
65
65
  appVersionId: targetAppVersion.id,
@@ -72,7 +72,7 @@ export class UpgradeApp extends ExecRenderBaseCommand {
72
72
  });
73
73
  if (missingDependencies.data.missingSystemSoftwareDependencies) {
74
74
  appUpgradePayload.systemSoftware = {};
75
- process.addStep(_jsxs(Text, { children: ["In order to upgrade your ", currentApp.name, " to Version", " ", targetAppVersion.externalVersion, " some dependencies need to be upgraded too."] }));
75
+ process.addStep(`In order to upgrade your ${currentApp.name} to Version ${targetAppVersion.externalVersion} some dependencies need to be upgraded too.`);
76
76
  for (const missingSystemSoftwareDependency of missingDependencies.data
77
77
  .missingSystemSoftwareDependencies) {
78
78
  const dependencyUpdateData = await updateMissingSystemSoftwareDependency(process, this.apiClient, missingSystemSoftwareDependency);
@@ -81,9 +81,9 @@ export class UpgradeApp extends ExecRenderBaseCommand {
81
81
  };
82
82
  }
83
83
  if (!this.flags.force) {
84
- const confirmed = await process.addConfirmation(_jsx(Text, { children: "Do you want to continue?" }));
84
+ const confirmed = await process.addConfirmation("Do you want to continue?");
85
85
  if (!confirmed) {
86
- process.addInfo(_jsx(Text, { children: "Upgrade will not be triggered." }));
86
+ process.addInfo("Upgrade will not be triggered.");
87
87
  process.complete(_jsx(_Fragment, {}));
88
88
  ux.exit(1);
89
89
  }
@@ -136,7 +136,7 @@ export class UpgradeApp extends ExecRenderBaseCommand {
136
136
  if (semverMatch) {
137
137
  return semverMatch;
138
138
  }
139
- process.addInfo(_jsx(Text, { children: "The given target upgrade version does not seem to be a valid upgrade candidate." }));
139
+ process.addInfo("The given target upgrade version does not seem to be a valid upgrade candidate.");
140
140
  }
141
141
  return await forceTargetVersionSelection(process, this.apiClient, targetAppVersionCandidates, currentApp, currentAppVersion);
142
142
  }
@@ -182,7 +182,7 @@ async function updateMissingSystemSoftwareDependency(process, apiClient, depende
182
182
  " could not be determined");
183
183
  }
184
184
  else {
185
- process.addInfo(_jsxs(Text, { children: [dependencySoftware.data.name, " will be upgraded to Version", " ", dependencyTargetVersion.externalVersion, "."] }));
185
+ process.addInfo(`${dependencySoftware.data.name} will be upgraded to Version ${dependencyTargetVersion.externalVersion}.`);
186
186
  return {
187
187
  dependencySoftwareId: dependencySoftware.data.id,
188
188
  dependencyTargetVersionId: dependencyTargetVersion.id,
@@ -6,7 +6,6 @@ import { Flags } from "@oclif/core";
6
6
  import { assertStatus } from "@mittwald/api-client-commons";
7
7
  import { Success } from "../../rendering/react/components/Success.js";
8
8
  import { waitFlags, waitUntil } from "../../lib/wait.js";
9
- import { Text } from "ink";
10
9
  import { expireFlags } from "../../lib/flags/expireFlags.js";
11
10
  export class Create extends ExecRenderBaseCommand {
12
11
  static summary = "Create a new backup of a project";
@@ -37,7 +36,7 @@ export class Create extends ExecRenderBaseCommand {
37
36
  return r.data;
38
37
  });
39
38
  if (this.flags.wait) {
40
- const stepWaiting = p.addStep(_jsx(Text, { children: "waiting for backup to be complete" }));
39
+ const stepWaiting = p.addStep("waiting for backup to be complete");
41
40
  await waitUntil(async () => {
42
41
  const backupResponse = await this.apiClient.backup.getProjectBackup({
43
42
  projectBackupId: backup.id,
@@ -3,7 +3,6 @@ import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseComm
3
3
  import { Flags } from "@oclif/core";
4
4
  import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
5
5
  import crypto from "crypto";
6
- import { Text } from "ink";
7
6
  import { Value } from "../../rendering/react/components/Value.js";
8
7
  import { assertStatus, } from "@mittwald/api-client-commons";
9
8
  import { waitUntil } from "../../lib/wait.js";
@@ -58,11 +57,11 @@ export class Download extends ExecRenderBaseCommand {
58
57
  const password = await p.runStep("generating password", async () => {
59
58
  return crypto.randomBytes(32).toString("ascii").substring(0, 32);
60
59
  });
61
- p.addInfo(_jsxs(Text, { children: ["generated password: ", _jsx(Value, { children: password })] }));
60
+ p.addInfo(`generated password: ${password}`);
62
61
  return password;
63
62
  }
64
63
  if (this.flags["prompt-password"]) {
65
- return await p.addInput(_jsx(Text, { children: "enter backup password" }), true);
64
+ return await p.addInput("enter backup password", true);
66
65
  }
67
66
  return undefined;
68
67
  }
@@ -79,7 +78,7 @@ export class Download extends ExecRenderBaseCommand {
79
78
  return r.data;
80
79
  });
81
80
  if (backup.export && backup.export.phase !== "Expired") {
82
- p.addInfo(_jsx(Text, { children: "backup download is already prepared" }));
81
+ p.addInfo("backup download is already prepared");
83
82
  }
84
83
  else {
85
84
  await p.runStep("preparing backup download", async () => {
@@ -115,7 +114,7 @@ export class Download extends ExecRenderBaseCommand {
115
114
  const stat = fs.statSync(this.flags.output);
116
115
  const range = `bytes=${stat.size}-`;
117
116
  reqConfig.headers = { Range: range };
118
- p.addInfo(_jsxs(Text, { children: ["resuming download starting at ", _jsx(Value, { children: stat.size }), " bytes"] }));
117
+ p.addInfo(`resuming download starting at ${stat.size} bytes`);
119
118
  }
120
119
  const downloadStep = p.addStep("downloading backup");
121
120
  const resp = await axios(backupExport.downloadURL, reqConfig);
@@ -10,16 +10,10 @@ export default class Exec extends ExtendedBaseCommand<typeof Exec> {
10
10
  workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
11
  env: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
12
  shell: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
14
  "project-id": import("@oclif/core/interfaces").OptionFlag<string>;
14
15
  "ssh-user": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
16
  "ssh-identity-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
17
  };
17
- /**
18
- * Prepare environment variables for the SSH command
19
- *
20
- * @param envVars Array of environment variables in KEY=VALUE format
21
- * @returns Formatted string with export commands
22
- */
23
- private prepareEnvironmentVariables;
24
18
  run(): Promise<void>;
25
19
  }
@@ -8,6 +8,7 @@ import { buildSSHClientFlags } from "../../lib/resources/ssh/connection.js";
8
8
  import { withContainerAndStackId } from "../../lib/resources/container/flags.js";
9
9
  import { projectFlags } from "../../lib/resources/project/flags.js";
10
10
  import shellEscape from "shell-escape";
11
+ import { prepareEnvironmentVariables } from "../../lib/resources/ssh/environment.js";
11
12
  export default class Exec extends ExtendedBaseCommand {
12
13
  static summary = "Execute a command in a container via SSH non-interactively.";
13
14
  static description = sshUsageDocumentation;
@@ -33,44 +34,32 @@ export default class Exec extends ExtendedBaseCommand {
33
34
  char: "e",
34
35
  summary: "environment variables to set for the command (format: KEY=VALUE)",
35
36
  multiple: true,
37
+ multipleNonGreedy: true,
36
38
  }),
37
39
  shell: Flags.string({
38
40
  summary: "shell to use for the SSH connection",
39
41
  default: "/bin/sh",
40
42
  }),
43
+ quiet: Flags.boolean({
44
+ char: "q",
45
+ summary: "disable informational output, only show command results",
46
+ default: false,
47
+ }),
41
48
  };
42
- /**
43
- * Prepare environment variables for the SSH command
44
- *
45
- * @param envVars Array of environment variables in KEY=VALUE format
46
- * @returns Formatted string with export commands
47
- */
48
- prepareEnvironmentVariables(envVars) {
49
- return (envVars
50
- .map((env) => {
51
- const eqIdx = env.indexOf("=");
52
- if (eqIdx === -1) {
53
- // If no '=', treat the whole string as key with empty value
54
- return `export ${shellEscape([env])}=`;
55
- }
56
- const key = env.slice(0, eqIdx);
57
- const value = env.slice(eqIdx + 1);
58
- return `export ${shellEscape([key])}=${shellEscape([value])}`;
59
- })
60
- .join("; ") + "; ");
61
- }
62
49
  async run() {
63
50
  const { args, flags } = await this.parse(Exec);
64
51
  const [containerId, stackId] = await withContainerAndStackId(this.apiClient, Exec, flags, this.args, this.config);
65
52
  const { host, user } = await getSSHConnectionForContainer(this.apiClient, containerId, stackId, flags["ssh-user"]);
66
- this.log("executing command on %s as %s", host, user);
53
+ if (!flags.quiet) {
54
+ this.log("executing command on %s as %s", host, user);
55
+ }
67
56
  const command = args.command;
68
57
  const workdir = flags.workdir;
69
58
  // Build the command to execute
70
59
  let execCommand = "";
71
60
  // Add environment variables if provided
72
61
  if (flags.env && flags.env.length > 0) {
73
- execCommand += this.prepareEnvironmentVariables(flags.env);
62
+ execCommand += prepareEnvironmentVariables(flags.env);
74
63
  }
75
64
  // Change to working directory if specified
76
65
  if (workdir !== undefined) {
@@ -1,7 +1,9 @@
1
1
  import { ReactNode } from "react";
2
2
  import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
3
+ import { MittwaldAPIV2 } from "@mittwald/api-client";
4
+ type ContainerServiceResponse = MittwaldAPIV2.Components.Schemas.ContainerServiceResponse;
3
5
  type Result = {
4
- serviceId: string;
6
+ service: ContainerServiceResponse;
5
7
  };
6
8
  export declare class Run extends ExecRenderBaseCommand<typeof Run, Result> {
7
9
  static summary: string;
@@ -56,6 +58,6 @@ export declare class Run extends ExecRenderBaseCommand<typeof Run, Result> {
56
58
  private buildServiceRequest;
57
59
  private getImageAndMeta;
58
60
  private getServiceName;
59
- protected render({ serviceId }: Result): ReactNode;
61
+ protected render({ service }: Result): ReactNode;
60
62
  }
61
63
  export {};