@mittwald/cli 1.0.0-alpha.27 → 1.0.0-alpha.28

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 (115) hide show
  1. package/README.md +814 -760
  2. package/dist/esm/ExtendedBaseCommand.d.ts +4 -0
  3. package/dist/esm/ExtendedBaseCommand.js +12 -0
  4. package/dist/esm/Formatter.js +13 -1
  5. package/dist/esm/GetBaseCommand.d.ts +2 -3
  6. package/dist/esm/GetBaseCommand.js +2 -4
  7. package/dist/esm/ListBaseCommand.d.ts +2 -3
  8. package/dist/esm/ListBaseCommand.js +2 -4
  9. package/dist/esm/commands/app/copy.d.ts +1 -1
  10. package/dist/esm/commands/app/copy.js +3 -3
  11. package/dist/esm/commands/app/dependency/list.d.ts +1 -1
  12. package/dist/esm/commands/app/dependency/update.d.ts +1 -1
  13. package/dist/esm/commands/app/dependency/update.js +3 -3
  14. package/dist/esm/commands/app/dependency/versions.d.ts +1 -1
  15. package/dist/esm/commands/app/get.d.ts +1 -1
  16. package/dist/esm/commands/app/get.js +4 -3
  17. package/dist/esm/commands/app/list.d.ts +1 -1
  18. package/dist/esm/commands/app/list.js +4 -0
  19. package/dist/esm/commands/app/ssh.d.ts +4 -3
  20. package/dist/esm/commands/app/ssh.js +18 -9
  21. package/dist/esm/commands/app/uninstall.d.ts +1 -1
  22. package/dist/esm/commands/app/uninstall.js +3 -6
  23. package/dist/esm/commands/backup/create.js +2 -2
  24. package/dist/esm/commands/backup/list.js +2 -2
  25. package/dist/esm/commands/context/get.js +27 -5
  26. package/dist/esm/commands/conversation/show.js +1 -2
  27. package/dist/esm/commands/cronjob/create.d.ts +22 -0
  28. package/dist/esm/commands/cronjob/create.js +96 -0
  29. package/dist/esm/commands/cronjob/delete.d.ts +13 -0
  30. package/dist/esm/commands/cronjob/delete.js +21 -0
  31. package/dist/esm/commands/cronjob/execute.d.ts +17 -0
  32. package/dist/esm/commands/cronjob/execute.js +42 -0
  33. package/dist/esm/commands/cronjob/execution/abort.d.ts +18 -0
  34. package/dist/esm/commands/cronjob/execution/abort.js +41 -0
  35. package/dist/esm/commands/cronjob/execution/list.js +4 -5
  36. package/dist/esm/commands/cronjob/get.d.ts +7 -9
  37. package/dist/esm/commands/cronjob/get.js +22 -12
  38. package/dist/esm/commands/cronjob/list.js +4 -6
  39. package/dist/esm/commands/database/mysql/charsets.d.ts +2 -4
  40. package/dist/esm/commands/database/mysql/charsets.js +2 -6
  41. package/dist/esm/commands/database/mysql/create.js +2 -2
  42. package/dist/esm/commands/database/mysql/delete.js +2 -2
  43. package/dist/esm/commands/database/mysql/list.d.ts +1 -2
  44. package/dist/esm/commands/database/mysql/list.js +2 -2
  45. package/dist/esm/commands/database/mysql/user/list.d.ts +1 -2
  46. package/dist/esm/commands/database/mysql/user/list.js +2 -3
  47. package/dist/esm/commands/database/mysql/versions.d.ts +1 -2
  48. package/dist/esm/commands/database/mysql/versions.js +1 -3
  49. package/dist/esm/commands/database/redis/create.js +2 -2
  50. package/dist/esm/commands/database/redis/get.d.ts +1 -3
  51. package/dist/esm/commands/database/redis/get.js +0 -3
  52. package/dist/esm/commands/database/redis/list.d.ts +1 -2
  53. package/dist/esm/commands/database/redis/list.js +3 -5
  54. package/dist/esm/commands/database/redis/versions.d.ts +1 -2
  55. package/dist/esm/commands/database/redis/versions.js +2 -3
  56. package/dist/esm/commands/domain/dnszone/list.d.ts +1 -2
  57. package/dist/esm/commands/domain/dnszone/list.js +2 -2
  58. package/dist/esm/commands/domain/list.d.ts +1 -2
  59. package/dist/esm/commands/domain/list.js +3 -4
  60. package/dist/esm/commands/domain/ownership/list.js +3 -7
  61. package/dist/esm/commands/domain/virtualhost/create.js +4 -4
  62. package/dist/esm/commands/domain/virtualhost/delete.js +1 -1
  63. package/dist/esm/commands/domain/virtualhost/get.js +1 -1
  64. package/dist/esm/commands/domain/virtualhost/list.d.ts +1 -3
  65. package/dist/esm/commands/domain/virtualhost/list.js +5 -8
  66. package/dist/esm/commands/mail/address/create.d.ts +4 -0
  67. package/dist/esm/commands/mail/address/create.js +59 -5
  68. package/dist/esm/commands/mail/address/list.d.ts +2 -2
  69. package/dist/esm/commands/mail/address/list.js +2 -4
  70. package/dist/esm/commands/mail/deliverybox/list.js +2 -2
  71. package/dist/esm/commands/project/create.js +2 -2
  72. package/dist/esm/commands/project/delete.d.ts +0 -1
  73. package/dist/esm/commands/project/delete.js +4 -8
  74. package/dist/esm/commands/project/filesystem/usage.d.ts +1 -1
  75. package/dist/esm/commands/project/filesystem/usage.js +3 -3
  76. package/dist/esm/commands/project/get.js +5 -5
  77. package/dist/esm/commands/project/invite/list.js +2 -2
  78. package/dist/esm/commands/project/membership/list.js +5 -5
  79. package/dist/esm/commands/project/ssh.d.ts +2 -2
  80. package/dist/esm/commands/project/ssh.js +4 -5
  81. package/dist/esm/commands/project/update.d.ts +2 -2
  82. package/dist/esm/commands/project/update.js +4 -5
  83. package/dist/esm/commands/server/get.d.ts +1 -3
  84. package/dist/esm/commands/server/get.js +2 -5
  85. package/dist/esm/commands/sftp-user/list.js +2 -2
  86. package/dist/esm/commands/ssh-user/list.js +2 -2
  87. package/dist/esm/lib/app/flags.d.ts +4 -2
  88. package/dist/esm/lib/app/flags.js +3 -7
  89. package/dist/esm/lib/assert_success.d.ts +3 -0
  90. package/dist/esm/lib/assert_success.js +7 -0
  91. package/dist/esm/lib/context.d.ts +24 -5
  92. package/dist/esm/lib/context.js +21 -16
  93. package/dist/esm/lib/context_flags.d.ts +10 -6
  94. package/dist/esm/lib/context_flags.js +8 -5
  95. package/dist/esm/lib/context_terraform.d.ts +6 -0
  96. package/dist/esm/lib/context_terraform.js +61 -0
  97. package/dist/esm/lib/context_user.d.ts +10 -0
  98. package/dist/esm/lib/context_user.js +34 -0
  99. package/dist/esm/lib/org/flags.d.ts +1 -9
  100. package/dist/esm/lib/org/flags.js +1 -1
  101. package/dist/esm/lib/project/flags.d.ts +1 -9
  102. package/dist/esm/lib/project/flags.js +1 -1
  103. package/dist/esm/lib/project/ingress.js +4 -2
  104. package/dist/esm/lib/server/flags.d.ts +1 -9
  105. package/dist/esm/lib/server/flags.js +1 -1
  106. package/dist/esm/rendering/react/RenderBaseCommand.d.ts +3 -0
  107. package/dist/esm/rendering/react/RenderBaseCommand.js +7 -0
  108. package/dist/esm/rendering/react/components/AppInstallation/AppInstallationDetails.js +8 -1
  109. package/dist/esm/rendering/react/components/CronJob/CronJobDetails.d.ts +8 -0
  110. package/dist/esm/rendering/react/components/CronJob/CronJobDetails.js +48 -0
  111. package/dist/esm/rendering/react/components/LocalFilename.d.ts +5 -0
  112. package/dist/esm/rendering/react/components/LocalFilename.js +14 -0
  113. package/dist/esm/rendering/react/components/Note.d.ts +1 -0
  114. package/dist/esm/rendering/react/components/Note.js +1 -1
  115. package/package.json +8 -6
@@ -1,7 +1,11 @@
1
1
  import { BaseCommand } from "./BaseCommand.js";
2
2
  import { CommandArgs, CommandFlags } from "./types.js";
3
+ import { CommandType } from "./lib/context_flags.js";
3
4
  export declare abstract class ExtendedBaseCommand<T extends typeof BaseCommand> extends BaseCommand {
4
5
  protected flags: CommandFlags<T>;
5
6
  protected args: CommandArgs<T>;
6
7
  init(): Promise<void>;
8
+ withAppInstallationId(command: CommandType<"installation"> | "flag" | "arg"): Promise<string>;
9
+ withProjectId(command: CommandType<"project"> | "flag" | "arg"): Promise<string>;
10
+ withServerId(command: CommandType<"server"> | "flag" | "arg"): Promise<string>;
7
11
  }
@@ -1,4 +1,7 @@
1
1
  import { BaseCommand } from "./BaseCommand.js";
2
+ import { withAppInstallationId } from "./lib/app/flags.js";
3
+ import { withProjectId } from "./lib/project/flags.js";
4
+ import { withServerId } from "./lib/server/flags.js";
2
5
  export class ExtendedBaseCommand extends BaseCommand {
3
6
  flags;
4
7
  args;
@@ -13,4 +16,13 @@ export class ExtendedBaseCommand extends BaseCommand {
13
16
  this.args = args;
14
17
  this.flags = flags;
15
18
  }
19
+ async withAppInstallationId(command) {
20
+ return withAppInstallationId(this.apiClient, command, this.flags, this.args, this.config);
21
+ }
22
+ async withProjectId(command) {
23
+ return withProjectId(this.apiClient, command, this.flags, this.args, this.config);
24
+ }
25
+ async withServerId(command) {
26
+ return withServerId(this.apiClient, command, this.flags, this.args, this.config);
27
+ }
16
28
  }
@@ -20,11 +20,23 @@ export class GetFormatter {
20
20
  }
21
21
  export class ListFormatter {
22
22
  static get flags() {
23
+ const tableFlags = ux.table.flags();
24
+ delete tableFlags.sort;
25
+ delete tableFlags.filter;
23
26
  return {
24
- ...ux.table.flags(),
27
+ ...tableFlags,
28
+ output: {
29
+ ...tableFlags.output,
30
+ options: ["json", "yaml", "csv"],
31
+ char: "o",
32
+ },
25
33
  };
26
34
  }
27
35
  log(output, columns, opts) {
36
+ if (opts?.output === "json" || opts?.output === "yaml") {
37
+ PrinterFactory.build(opts.output).log(output);
38
+ return;
39
+ }
28
40
  if (output.length === 0) {
29
41
  return;
30
42
  }
@@ -2,14 +2,13 @@ import { Command, Interfaces } from "@oclif/core";
2
2
  import { BaseCommand } from "./BaseCommand.js";
3
3
  import { GetFormatter } from "./Formatter.js";
4
4
  import { Response } from "@mittwald/api-client-commons";
5
+ import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
5
6
  export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof GetBaseCommand)["baseFlags"] & T["flags"]>;
6
7
  export type Args<T extends typeof Command> = Interfaces.InferredArgs<T["args"]>;
7
- export declare abstract class GetBaseCommand<T extends typeof BaseCommand, TAPIResponse extends Response> extends BaseCommand {
8
+ export declare abstract class GetBaseCommand<T extends typeof BaseCommand, TAPIResponse extends Response> extends ExtendedBaseCommand<T> {
8
9
  static baseFlags: {
9
10
  [x: string]: Interfaces.Flag<any>;
10
11
  };
11
- protected flags: Flags<T>;
12
- protected args: Args<T>;
13
12
  protected formatter: GetFormatter;
14
13
  init(): Promise<void>;
15
14
  run(): Promise<void>;
@@ -1,12 +1,10 @@
1
- import { BaseCommand } from "./BaseCommand.js";
2
1
  import { GetFormatter } from "./Formatter.js";
3
2
  import { assertStatus } from "@mittwald/api-client-commons";
4
- export class GetBaseCommand extends BaseCommand {
3
+ import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
4
+ export class GetBaseCommand extends ExtendedBaseCommand {
5
5
  static baseFlags = {
6
6
  ...GetFormatter.flags,
7
7
  };
8
- flags;
9
- args;
10
8
  formatter = new GetFormatter();
11
9
  async init() {
12
10
  await super.init();
@@ -3,14 +3,13 @@ import { BaseCommand } from "./BaseCommand.js";
3
3
  import { ListColumns, ListFormatter } from "./Formatter.js";
4
4
  import { Response } from "@mittwald/api-client-commons";
5
5
  import { SuccessfulResponse } from "./types.js";
6
+ import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
6
7
  export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof ListBaseCommand)["baseFlags"] & T["flags"]>;
7
8
  export type Args<T extends typeof Command> = Interfaces.InferredArgs<T["args"]>;
8
- export declare abstract class ListBaseCommand<T extends typeof BaseCommand, TItem extends Record<string, unknown>, TAPIResponse extends Response> extends BaseCommand {
9
+ export declare abstract class ListBaseCommand<T extends typeof BaseCommand, TItem extends Record<string, unknown>, TAPIResponse extends Response> extends ExtendedBaseCommand<T> {
9
10
  static baseFlags: {
10
11
  [x: string]: Interfaces.Flag<any>;
11
12
  };
12
- protected flags: Flags<T>;
13
- protected args: Args<T>;
14
13
  protected formatter: ListFormatter;
15
14
  init(): Promise<void>;
16
15
  run(): Promise<void>;
@@ -1,13 +1,11 @@
1
- import { BaseCommand } from "./BaseCommand.js";
2
1
  import { ListFormatter } from "./Formatter.js";
3
2
  import { assertStatus } from "@mittwald/api-client-commons";
4
3
  import { formatRelativeDate } from "./lib/viewhelpers/date.js";
5
- export class ListBaseCommand extends BaseCommand {
4
+ import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
5
+ export class ListBaseCommand extends ExtendedBaseCommand {
6
6
  static baseFlags = {
7
7
  ...ListFormatter.flags,
8
8
  };
9
- flags;
10
- args;
11
9
  formatter = new ListFormatter();
12
10
  async init() {
13
11
  await super.init();
@@ -6,7 +6,7 @@ type Result = {
6
6
  export declare class Copy extends ExecRenderBaseCommand<typeof Copy, Result> {
7
7
  static description: string;
8
8
  static args: {
9
- "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
9
+ "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string>;
10
10
  };
11
11
  static flags: {
12
12
  description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
@@ -1,13 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { ExecRenderBaseCommand } from "../../rendering/react/ExecRenderBaseCommand.js";
3
- import { appInstallationFlags } from "../../lib/app/flags.js";
3
+ import { appInstallationArgs } from "../../lib/app/flags.js";
4
4
  import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
5
5
  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
  export class Copy extends ExecRenderBaseCommand {
9
9
  static description = "Copy an app within a project";
10
- static args = { ...appInstallationFlags };
10
+ static args = { ...appInstallationArgs };
11
11
  static flags = {
12
12
  ...processFlags,
13
13
  description: Flags.string({
@@ -16,7 +16,7 @@ export class Copy extends ExecRenderBaseCommand {
16
16
  }),
17
17
  };
18
18
  async exec() {
19
- const { "installation-id": id } = this.args;
19
+ const id = await this.withAppInstallationId(Copy);
20
20
  const { description } = this.flags;
21
21
  const p = makeProcessRenderer(this.flags, "Copying app installation");
22
22
  const result = await p.runStep("requesting app copy", async () => {
@@ -3,7 +3,7 @@ import { MittwaldAPIV2, MittwaldAPIV2Client } from "@mittwald/api-client";
3
3
  import { SuccessfulResponse } from "../../../types.js";
4
4
  import { ListBaseCommand } from "../../../ListBaseCommand.js";
5
5
  import { ListColumns } from "../../../Formatter.js";
6
- type ResponseItem = Simplify<MittwaldAPIV2.Paths.V2Systemsoftwares.Get.Responses.$200.Content.ApplicationJson[number]>;
6
+ type ResponseItem = Simplify<MittwaldAPIV2.Paths.V2SystemSoftwares.Get.Responses.$200.Content.ApplicationJson[number]>;
7
7
  type Response = Awaited<ReturnType<MittwaldAPIV2Client["app"]["listSystemsoftwares"]>>;
8
8
  export declare class List extends ListBaseCommand<typeof List, ResponseItem, Response> {
9
9
  static description: string;
@@ -3,7 +3,7 @@ import { ReactNode } from "react";
3
3
  export default class Update extends ExecRenderBaseCommand<typeof Update, void> {
4
4
  static summary: string;
5
5
  static args: {
6
- "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
6
+ "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string>;
7
7
  };
8
8
  static examples: {
9
9
  description: string;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ExecRenderBaseCommand } from "../../../rendering/react/ExecRenderBaseCommand.js";
3
- import { appInstallationFlags } from "../../../lib/app/flags.js";
3
+ import { appInstallationArgs } from "../../../lib/app/flags.js";
4
4
  import { makeProcessRenderer, processFlags, } from "../../../rendering/process/process_flags.js";
5
5
  import { Flags } from "@oclif/core";
6
6
  import { assertStatus } from "@mittwald/api-client-commons";
@@ -10,7 +10,7 @@ import { Value } from "../../../rendering/react/components/Value.js";
10
10
  import { Text } from "ink";
11
11
  export default class Update extends ExecRenderBaseCommand {
12
12
  static summary = "Update the dependencies of an app";
13
- static args = { ...appInstallationFlags };
13
+ static args = { ...appInstallationArgs };
14
14
  static examples = [
15
15
  {
16
16
  description: "Update Node.js version to newest available from the 18.x branch",
@@ -35,7 +35,7 @@ export default class Update extends ExecRenderBaseCommand {
35
35
  }),
36
36
  };
37
37
  async exec() {
38
- const appInstallationId = this.args["installation-id"];
38
+ const appInstallationId = await this.withAppInstallationId(Update);
39
39
  const updatePolicy = this.flags["update-policy"];
40
40
  const process = makeProcessRenderer(this.flags, "Updating app dependencies");
41
41
  const systemSoftwares = await process.runStep("fetching system softwares", async () => {
@@ -3,7 +3,7 @@ import { MittwaldAPIV2, MittwaldAPIV2Client } from "@mittwald/api-client";
3
3
  import { ListBaseCommand } from "../../../ListBaseCommand.js";
4
4
  import { SuccessfulResponse } from "../../../types.js";
5
5
  import { ListColumns } from "../../../Formatter.js";
6
- type ResponseItem = Simplify<MittwaldAPIV2.Paths.V2SystemsoftwareSystemSoftwareIdVersions.Get.Responses.$200.Content.ApplicationJson[number]>;
6
+ type ResponseItem = Simplify<MittwaldAPIV2.Paths.V2SystemSoftwareSystemSoftwareIdVersions.Get.Responses.$200.Content.ApplicationJson[number]>;
7
7
  type Response = Awaited<ReturnType<MittwaldAPIV2Client["app"]["listSystemsoftwareversions"]>>;
8
8
  export declare class Versions extends ListBaseCommand<typeof Versions, ResponseItem, Response> {
9
9
  static description: string;
@@ -6,7 +6,7 @@ export default class Get extends RenderBaseCommand<typeof Get> {
6
6
  [x: string]: import("@oclif/core/lib/interfaces/parser.js").Flag<any>;
7
7
  };
8
8
  static args: {
9
- "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
9
+ "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string>;
10
10
  };
11
11
  protected render(): ReactNode;
12
12
  }
@@ -4,13 +4,14 @@ import { RenderJson } from "../../rendering/react/json/RenderJson.js";
4
4
  import { GetBaseCommand } from "../../GetBaseCommand.js";
5
5
  import { AppInstallationDetails } from "../../rendering/react/components/AppInstallation/AppInstallationDetails.js";
6
6
  import { useApp, useAppInstallation } from "../../lib/app/hooks.js";
7
- import { appInstallationFlags } from "../../lib/app/flags.js";
7
+ import { appInstallationArgs } from "../../lib/app/flags.js";
8
8
  export default class Get extends RenderBaseCommand {
9
9
  static description = "Get details about an app installation";
10
10
  static flags = { ...GetBaseCommand.baseFlags };
11
- static args = { ...appInstallationFlags };
11
+ static args = { ...appInstallationArgs };
12
12
  render() {
13
- const appInstallation = useAppInstallation(this.args["installation-id"]);
13
+ const appInstallationId = this.useAppInstallationId(Get);
14
+ const appInstallation = useAppInstallation(appInstallationId);
14
15
  const app = useApp(appInstallation.appId);
15
16
  if (this.flags.output === "json") {
16
17
  return _jsx(RenderJson, { name: "appInstallation", data: appInstallation });
@@ -5,7 +5,7 @@ import { SuccessfulResponse } from "../../types.js";
5
5
  import { ListColumns } from "../../Formatter.js";
6
6
  import AppApp = MittwaldAPIV2.Components.Schemas.AppApp;
7
7
  import AppAppVersion = MittwaldAPIV2.Components.Schemas.AppAppVersion;
8
- type ResponseItem = Simplify<MittwaldAPIV2.Paths.V2ProjectsProjectIdAppinstallations.Get.Responses.$200.Content.ApplicationJson[number]>;
8
+ type ResponseItem = Simplify<MittwaldAPIV2.Paths.V2ProjectsProjectIdAppInstallations.Get.Responses.$200.Content.ApplicationJson[number]>;
9
9
  type Response = Awaited<ReturnType<MittwaldAPIV2Client["app"]["listAppinstallations"]>>;
10
10
  type ExtendedResponseItem = ResponseItem & {
11
11
  app: AppApp;
@@ -36,6 +36,10 @@ export default class List extends ListBaseCommand {
36
36
  header: "ID",
37
37
  minWidth: 36,
38
38
  },
39
+ shortId: {
40
+ header: "Short ID",
41
+ minWidth: 8,
42
+ },
39
43
  description: {},
40
44
  app: {
41
45
  header: "Application",
@@ -1,11 +1,12 @@
1
- import { BaseCommand } from "../../BaseCommand.js";
2
- export default class Ssh extends BaseCommand {
1
+ import { ExtendedBaseCommand } from "../../ExtendedBaseCommand.js";
2
+ export default class Ssh extends ExtendedBaseCommand<typeof Ssh> {
3
3
  static description: string;
4
4
  static args: {
5
- "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
5
+ "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string>;
6
6
  };
7
7
  static flags: {
8
8
  cd: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
+ info: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
9
10
  };
10
11
  run(): Promise<void>;
11
12
  }
@@ -1,24 +1,27 @@
1
- import { BaseCommand } from "../../BaseCommand.js";
2
1
  import { assertStatus } from "@mittwald/api-client-commons";
3
2
  import * as child_process from "child_process";
4
- import { appInstallationFlags } from "../../lib/app/flags.js";
3
+ import { appInstallationArgs } from "../../lib/app/flags.js";
5
4
  import { Flags } from "@oclif/core";
6
5
  import * as path from "path";
7
- export default class Ssh extends BaseCommand {
6
+ import { ExtendedBaseCommand } from "../../ExtendedBaseCommand.js";
7
+ export default class Ssh extends ExtendedBaseCommand {
8
8
  static description = "Connect to an app via SSH";
9
- static args = { ...appInstallationFlags };
9
+ static args = { ...appInstallationArgs };
10
10
  static flags = {
11
11
  cd: Flags.boolean({
12
12
  summary: "change to installation path after connecting",
13
13
  default: true,
14
14
  allowNo: true,
15
15
  }),
16
+ info: Flags.boolean({
17
+ summary: "only print connection information, without actually connecting",
18
+ }),
16
19
  };
17
20
  async run() {
18
- const { args, flags } = await this.parse(Ssh);
19
- const id = args["installation-id"];
21
+ const { flags } = await this.parse(Ssh);
22
+ const appInstallationId = await this.withAppInstallationId(Ssh);
20
23
  const appInstallationResponse = await this.apiClient.app.getAppinstallation({
21
- appInstallationId: id,
24
+ appInstallationId,
22
25
  });
23
26
  assertStatus(appInstallationResponse, 200);
24
27
  if (appInstallationResponse.data.projectId === undefined) {
@@ -31,11 +34,17 @@ export default class Ssh extends BaseCommand {
31
34
  const userResponse = await this.apiClient.user.getOwnAccount();
32
35
  assertStatus(userResponse, 200);
33
36
  const sshHost = `ssh.${projectResponse.data.clusterID}.${projectResponse.data.clusterDomain}`;
34
- const sshUser = `${userResponse.data.email}@app-${appInstallationResponse.data.id}`;
37
+ const sshUser = `${userResponse.data.email}@${appInstallationResponse.data.shortId}`;
38
+ const absoluteInstallPath = path.join(projectResponse.data.directories["Web"], appInstallationResponse.data.installationPath);
39
+ if (flags.info) {
40
+ this.log("hostname: %o", sshHost);
41
+ this.log("username: %o", sshUser);
42
+ this.log("directory: %o", absoluteInstallPath);
43
+ return;
44
+ }
35
45
  this.log("connecting to %o as %o", sshHost, sshUser);
36
46
  let cmd = "exec bash -l";
37
47
  if (flags.cd) {
38
- const absoluteInstallPath = path.join(projectResponse.data.directories["Web"], appInstallationResponse.data.installationPath);
39
48
  cmd = flags.cd ? `cd ${absoluteInstallPath} && exec bash -l` : "bash -l";
40
49
  this.log("changing to %o; use --no-cd to disable this behaviour", absoluteInstallPath);
41
50
  }
@@ -3,7 +3,7 @@ export default class Uninstall extends DeleteBaseCommand<typeof Uninstall> {
3
3
  static description: string;
4
4
  static resourceName: string;
5
5
  static args: {
6
- "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
6
+ "installation-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string>;
7
7
  };
8
8
  protected deleteResource(): Promise<void>;
9
9
  }
@@ -1,17 +1,14 @@
1
- import { Args } from "@oclif/core";
2
1
  import { assertStatus } from "@mittwald/api-client-commons";
3
2
  import { DeleteBaseCommand } from "../../DeleteBaseCommand.js";
3
+ import { appInstallationArgs } from "../../lib/app/flags.js";
4
4
  export default class Uninstall extends DeleteBaseCommand {
5
5
  static description = "Uninstall an app";
6
6
  static resourceName = "app installation";
7
7
  static args = {
8
- "installation-id": Args.string({
9
- description: "ID of the app installation to delete",
10
- required: true,
11
- }),
8
+ ...appInstallationArgs,
12
9
  };
13
10
  async deleteResource() {
14
- const appInstallationId = this.args["installation-id"];
11
+ const appInstallationId = await this.withAppInstallationId(Uninstall);
15
12
  const response = await this.apiClient.app.uninstallAppinstallation({
16
13
  appInstallationId,
17
14
  });
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { ExecRenderBaseCommand } from "../../rendering/react/ExecRenderBaseCommand.js";
3
3
  import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
4
- import { projectFlags, withProjectId } from "../../lib/project/flags.js";
4
+ import { projectFlags } from "../../lib/project/flags.js";
5
5
  import { Flags } from "@oclif/core";
6
6
  import { expirationDateFromFlags, expireFlagsRequired, } from "../../lib/expires.js";
7
7
  import { assertStatus } from "@mittwald/api-client-commons";
@@ -23,7 +23,7 @@ export class Create extends ExecRenderBaseCommand {
23
23
  static deprecateAliases = true;
24
24
  async exec() {
25
25
  const p = makeProcessRenderer(this.flags, "Creating backup");
26
- const projectId = await withProjectId(this.apiClient, Create, this.flags, this.args, this.config);
26
+ const projectId = await this.withProjectId(Create);
27
27
  const { description } = this.flags;
28
28
  const expirationTime = expirationDateFromFlags(this.flags);
29
29
  const backup = await p.runStep("creating backup", async () => {
@@ -1,5 +1,5 @@
1
1
  import { ListBaseCommand } from "../../ListBaseCommand.js";
2
- import { projectFlags, withProjectId } from "../../lib/project/flags.js";
2
+ import { projectFlags } from "../../lib/project/flags.js";
3
3
  import { formatRelativeDate } from "../../lib/viewhelpers/date.js";
4
4
  export class List extends ListBaseCommand {
5
5
  static description = "List Backups for a given Project.";
@@ -14,7 +14,7 @@ export class List extends ListBaseCommand {
14
14
  return data;
15
15
  }
16
16
  async getData() {
17
- const projectId = await withProjectId(this.apiClient, List, this.flags, {}, this.config);
17
+ const projectId = await this.withProjectId(List);
18
18
  return await this.apiClient.backup.listProjectBackups({
19
19
  projectId,
20
20
  });
@@ -1,23 +1,45 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { RenderBaseCommand } from "../../rendering/react/RenderBaseCommand.js";
3
- import { Context } from "../../lib/context.js";
3
+ import { Context, } from "../../lib/context.js";
4
4
  import { SingleResult } from "../../rendering/react/components/SingleResult.js";
5
5
  import { Value } from "../../rendering/react/components/Value.js";
6
6
  import { usePromise } from "@mittwald/react-use-promise";
7
7
  import { Note } from "../../rendering/react/components/Note.js";
8
- import { Box } from "ink";
8
+ import { Box, Text } from "ink";
9
9
  import { Set } from "./set.js";
10
10
  import { RenderJson } from "../../rendering/react/json/RenderJson.js";
11
11
  import { useRenderContext } from "../../rendering/react/context.js";
12
+ import { LocalFilename } from "../../rendering/react/components/LocalFilename.js";
13
+ const ContextSourceValue = ({ source }) => {
14
+ switch (source.type) {
15
+ case "user":
16
+ return (_jsxs(Text, { children: [_jsx(Text, { color: "yellow", children: "user configuration" }), ", in", " ", _jsx(LocalFilename, { filename: source.identifier })] }));
17
+ case "terraform":
18
+ return (_jsxs(Text, { children: [_jsx(Text, { color: "yellow", children: "terraform state file" }), ", in", " ", _jsx(LocalFilename, { filename: source.identifier, relative: true })] }));
19
+ default:
20
+ return _jsx(Text, { color: "yellow", children: "unknown" });
21
+ }
22
+ };
23
+ const ContextSource = ({ source }) => {
24
+ return (_jsxs(Text, { color: "gray", children: ["(source: ", _jsx(ContextSourceValue, { source: source }), ")"] }));
25
+ };
12
26
  const GetContext = ({ ctx }) => {
13
27
  const rows = {};
14
28
  const { renderAsJson } = useRenderContext();
15
29
  const values = {};
16
- for (const key of ["project-id", "server-id", "org-id"]) {
30
+ let hasTerraformSource = false;
31
+ for (const key of [
32
+ "project-id",
33
+ "server-id",
34
+ "org-id",
35
+ "installation-id",
36
+ ]) {
17
37
  const value = usePromise(ctx.getContextValue.bind(ctx), [key]);
18
38
  if (value) {
19
- rows[`--${key}`] = _jsx(Value, { children: value });
39
+ rows[`--${key}`] = (_jsxs(Text, { children: [_jsx(Value, { children: value.value }), " ", _jsx(ContextSource, { source: value.source })] }));
20
40
  values[key] = value;
41
+ hasTerraformSource =
42
+ hasTerraformSource || value.source.type === "terraform";
21
43
  }
22
44
  else {
23
45
  rows[`--${key}`] = _jsx(Value, { notSet: true });
@@ -26,7 +48,7 @@ const GetContext = ({ ctx }) => {
26
48
  if (renderAsJson) {
27
49
  return _jsx(RenderJson, { name: "context", data: values });
28
50
  }
29
- return (_jsx(_Fragment, { children: _jsxs(Box, { flexDirection: "column", children: [_jsx(SingleResult, { title: "Current CLI context", rows: rows }), _jsxs(Note, { marginY: 1, children: ["Use the ", _jsx(Value, { children: "mw context set" }), " command to set one of the values listed above."] })] }) }));
51
+ return (_jsx(_Fragment, { children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(SingleResult, { title: "Current CLI context", rows: rows }) }), hasTerraformSource && (_jsx(Note, { marginBottom: 1, children: "You are in a directory that contains a terraform state file; some of the context values were read from there." })), _jsxs(Note, { marginBottom: 1, children: ["Use the ", _jsx(Value, { children: "mw context set" }), " command to set one of the values listed above."] })] }) }));
30
52
  };
31
53
  export class Get extends RenderBaseCommand {
32
54
  static summary = "Print an overview of currently set context parameters";
@@ -45,10 +45,9 @@ export default class Show extends BaseCommand {
45
45
  for (const msg of messagesResponse.data) {
46
46
  if (msg.type === "MESSAGE") {
47
47
  console.log(chalk.whiteBright.underline(`${msg.createdBy?.clearName}, ${formatRelativeDate(msg.createdAt)}`));
48
- const rendered = marked(msg.messageContent ?? "")
48
+ const rendered = (await marked(msg.messageContent ?? ""))
49
49
  .trim()
50
50
  .split("\n")
51
- //.map((l) => `| ${l}`)
52
51
  .join("\n");
53
52
  console.log(rendered);
54
53
  console.log();
@@ -0,0 +1,22 @@
1
+ import { ExecRenderBaseCommand } from "../../rendering/react/ExecRenderBaseCommand.js";
2
+ import { ReactNode } from "react";
3
+ type Result = {
4
+ cronjobId: string;
5
+ };
6
+ export declare class Create extends ExecRenderBaseCommand<typeof Create, Result> {
7
+ static summary: string;
8
+ static flags: {
9
+ description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ interval: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ disable: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
12
+ email: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
+ url: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
+ interpreter: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
15
+ command: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
17
+ "installation-id": import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string>;
18
+ };
19
+ protected exec(): Promise<Result>;
20
+ protected render({ cronjobId }: Result): ReactNode;
21
+ }
22
+ export {};
@@ -0,0 +1,96 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ExecRenderBaseCommand } from "../../rendering/react/ExecRenderBaseCommand.js";
3
+ import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
4
+ import { Flags } from "@oclif/core";
5
+ import { assertStatus } from "@mittwald/api-client-commons";
6
+ import { Success } from "../../rendering/react/components/Success.js";
7
+ import { Value } from "../../rendering/react/components/Value.js";
8
+ import { appInstallationFlags } from "../../lib/app/flags.js";
9
+ export class Create extends ExecRenderBaseCommand {
10
+ static summary = "Create a new cron job";
11
+ static flags = {
12
+ ...appInstallationFlags,
13
+ ...processFlags,
14
+ description: Flags.string({
15
+ required: true,
16
+ summary: "Description of the cron job",
17
+ default: undefined,
18
+ }),
19
+ interval: Flags.string({
20
+ required: true,
21
+ summary: "Interval of the cron job, in standard UNIX cron syntax",
22
+ default: undefined,
23
+ }),
24
+ disable: Flags.boolean({
25
+ summary: "Disable the cron job after creation",
26
+ default: false,
27
+ }),
28
+ email: Flags.string({
29
+ required: false,
30
+ summary: "Email address to send cron job output to",
31
+ default: undefined,
32
+ }),
33
+ url: Flags.string({
34
+ required: false,
35
+ summary: "URL to call for the cron job; either this or `--command` is required.",
36
+ default: undefined,
37
+ exclusive: ["command"],
38
+ }),
39
+ interpreter: Flags.string({
40
+ required: false,
41
+ summary: "Interpreter to use for the cron job",
42
+ default: "/bin/sh",
43
+ }),
44
+ command: Flags.string({
45
+ required: false,
46
+ summary: "Command to execute for the cron job; either this or `--url` is required.",
47
+ default: undefined,
48
+ exclusive: ["url"],
49
+ }),
50
+ };
51
+ async exec() {
52
+ const p = makeProcessRenderer(this.flags, "Creating a new cron job");
53
+ const appInstallationId = await this.withAppInstallationId(Create);
54
+ const { description, interval, disable, email, url, interpreter, command } = this.flags;
55
+ if (!url && !command) {
56
+ throw new Error("either `--url` or `--command` must be specified");
57
+ }
58
+ const { projectId } = await p.runStep("fetching project", async () => {
59
+ const r = await this.apiClient.app.getAppinstallation({
60
+ appInstallationId,
61
+ });
62
+ assertStatus(r, 200);
63
+ return r.data;
64
+ });
65
+ if (!projectId) {
66
+ throw new Error("no project found for app installation");
67
+ }
68
+ const { id: cronjobId } = await p.runStep("creating cron job", async () => {
69
+ const r = await this.apiClient.cronjob.createCronjob({
70
+ projectId,
71
+ data: {
72
+ appId: appInstallationId,
73
+ active: !disable,
74
+ description,
75
+ interval,
76
+ email,
77
+ destination: url ? { url } : { interpreter, path: command },
78
+ },
79
+ });
80
+ assertStatus(r, 201);
81
+ return r.data;
82
+ });
83
+ const cronjob = await p.runStep("fetching cron job", async () => {
84
+ const r = await this.apiClient.cronjob.getCronjob({ cronjobId });
85
+ assertStatus(r, 200);
86
+ return r.data;
87
+ });
88
+ p.complete(_jsxs(Success, { children: ["The cron job ", _jsx(Value, { children: cronjob.shortId }), " was successfully created."] }));
89
+ return { cronjobId };
90
+ }
91
+ render({ cronjobId }) {
92
+ if (this.flags.quiet) {
93
+ return cronjobId;
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,13 @@
1
+ import { DeleteBaseCommand } from "../../DeleteBaseCommand.js";
2
+ export default class Delete extends DeleteBaseCommand<typeof Delete> {
3
+ static description: string;
4
+ static resourceName: string;
5
+ static flags: {
6
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
7
+ quiet: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
8
+ };
9
+ static args: {
10
+ "cronjob-id": import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
11
+ };
12
+ protected deleteResource(): Promise<void>;
13
+ }