@mittwald/cli 1.0.0-beta.3 → 1.1.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.
@@ -0,0 +1,9 @@
1
+ import { ExtendedBaseCommand } from "../../lib/basecommands/ExtendedBaseCommand.js";
2
+ export declare class Open extends ExtendedBaseCommand<typeof Open> {
3
+ static summary: string;
4
+ static description: string;
5
+ static args: {
6
+ "installation-id": import("@oclif/core/interfaces").Arg<string>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,29 @@
1
+ import { assertStatus } from "@mittwald/api-client-commons";
2
+ import open from "open";
3
+ import { appInstallationArgs, withAppInstallationId, } from "../../lib/resources/app/flags.js";
4
+ import { ExtendedBaseCommand } from "../../lib/basecommands/ExtendedBaseCommand.js";
5
+ import buildAppURLsFromIngressList from "../../lib/resources/app/buildAppURLsFromIngressList.js";
6
+ export class Open extends ExtendedBaseCommand {
7
+ static summary = "Open an app installation in the browser.";
8
+ static description = "This command opens an app installation in the browser. For this to work, there needs to be at least one virtual host linked to the app installation.";
9
+ static args = { ...appInstallationArgs };
10
+ async run() {
11
+ const appInstallationId = await withAppInstallationId(this.apiClient, Open, this.flags, this.args, this.config);
12
+ const installation = await this.apiClient.app.getAppinstallation({
13
+ appInstallationId,
14
+ });
15
+ assertStatus(installation, 200);
16
+ const domains = await this.apiClient.domain.ingressListIngresses({
17
+ queryParameters: {
18
+ projectId: installation.data.projectId,
19
+ },
20
+ });
21
+ assertStatus(domains, 200);
22
+ const urls = buildAppURLsFromIngressList(domains.data, installation.data.id);
23
+ if (urls.length === 0) {
24
+ throw new Error("This app installation is not linked to any virtual hosts.");
25
+ }
26
+ console.log("opening " + urls[0]);
27
+ await open(urls[0]);
28
+ }
29
+ }
@@ -26,7 +26,9 @@ export class List extends ListBaseCommand {
26
26
  const columns = {
27
27
  id: baseColumns.id,
28
28
  projectId: { header: "Project ID" },
29
- hostname: {},
29
+ hostname: {
30
+ get: (r) => `https://${r.hostname}`,
31
+ },
30
32
  paths: {
31
33
  get: (r) => r.paths
32
34
  .map((p) => {
@@ -0,0 +1,12 @@
1
+ import { MittwaldAPIV2 } from "@mittwald/api-client";
2
+ type Ingress = MittwaldAPIV2.Components.Schemas.IngressIngress;
3
+ /**
4
+ * Build a list of URLs for an app installation from a list of ingresses.
5
+ *
6
+ * @param ingresses A list of ingresses to search for the app installation ID;
7
+ * typically all ingresses for a project
8
+ * @param appInstallationId The ID of the app installation to search for
9
+ * @returns A list of URLs that point to the app installation
10
+ */
11
+ export default function buildAppURLsFromIngressList(ingresses: Ingress[], appInstallationId: string): string[];
12
+ export {};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Build a list of URLs for an app installation from a list of ingresses.
3
+ *
4
+ * @param ingresses A list of ingresses to search for the app installation ID;
5
+ * typically all ingresses for a project
6
+ * @param appInstallationId The ID of the app installation to search for
7
+ * @returns A list of URLs that point to the app installation
8
+ */
9
+ export default function buildAppURLsFromIngressList(ingresses, appInstallationId) {
10
+ const matchingURLs = [];
11
+ for (const virtualHost of ingresses) {
12
+ for (const path of virtualHost.paths) {
13
+ if ("installationId" in path.target &&
14
+ path.target.installationId === appInstallationId) {
15
+ matchingURLs.push("https://" + virtualHost.hostname + path.path);
16
+ }
17
+ }
18
+ }
19
+ return matchingURLs;
20
+ }
@@ -0,0 +1 @@
1
+ export declare function useVirtualHosts(projectId: string): import("@mittwald/api-client").MittwaldAPIV2.Components.Schemas.IngressIngress[];
@@ -0,0 +1,11 @@
1
+ import { assertStatus } from "@mittwald/api-client";
2
+ import { useRenderContext } from "../../../../rendering/react/context.js";
3
+ import { usePromise } from "@mittwald/react-use-promise";
4
+ export function useVirtualHosts(projectId) {
5
+ const { apiClient } = useRenderContext();
6
+ const virtualHosts = usePromise((projectId) => apiClient.domain.ingressListIngresses({
7
+ queryParameters: { projectId },
8
+ }), [projectId]);
9
+ assertStatus(virtualHosts, 200);
10
+ return virtualHosts.data;
11
+ }
@@ -11,6 +11,7 @@ import path from "path";
11
11
  import { isCustomAppInstallation } from "../../../../lib/resources/app/custom_installation.js";
12
12
  import maybe from "../../../../lib/util/maybe.js";
13
13
  import OptionalValue from "../OptionalValue.js";
14
+ import { AppVirtualHosts } from "./AppVirtualHosts.js";
14
15
  export const AppInstallationDetails = ({ app, appInstallation }) => {
15
16
  const desiredAppVersion = useAppVersion(app.id, appInstallation.appVersion.desired);
16
17
  const currentAppVersion = maybe(useAppVersion)(app.id, appInstallation.appVersion.current);
@@ -46,6 +47,7 @@ export const AppInstallationDetails = ({ app, appInstallation }) => {
46
47
  "SSH/SFTP Host": (_jsxs(Text, { children: [_jsxs(Value, { children: ["ssh.", project?.clusterID, ".", project?.clusterDomain] }), " ", _jsx(Text, { color: "gray", children: "(Use the \"app ssh\" command to connect directly using the CLI)" })] })),
47
48
  } }, "access"),
48
49
  _jsx(AppSystemSoftware, { appInstallation: appInstallation }, "systemsoftware"),
50
+ _jsx(AppVirtualHosts, { appInstallation: appInstallation }, "virtualhosts"),
49
51
  ];
50
52
  return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: sections }));
51
53
  };
@@ -0,0 +1,15 @@
1
+ import { FC } from "react";
2
+ import { MittwaldAPIV2 } from "@mittwald/api-client";
3
+ type AppAppInstallation = MittwaldAPIV2.Components.Schemas.AppAppInstallation;
4
+ /**
5
+ * Component to display the virtual hosts linked to an app installation. There
6
+ * is no specific API endpoint to fetch this information, so we have to fetch
7
+ * all virtual hosts and filter them by the installation ID.
8
+ *
9
+ * @class
10
+ * @param appInstallation
11
+ */
12
+ export declare const AppVirtualHosts: FC<{
13
+ appInstallation: AppAppInstallation;
14
+ }>;
15
+ export {};
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import maybe from "../../../../lib/util/maybe.js";
3
+ import { useVirtualHosts } from "../../../../lib/resources/domain/virtualhost/hooks.js";
4
+ import { Header } from "../Header.js";
5
+ import { Box, Text } from "ink";
6
+ import buildAppURLsFromIngressList from "../../../../lib/resources/app/buildAppURLsFromIngressList.js";
7
+ const AppVirtualHostBox = ({ children }) => {
8
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginY: 1, children: _jsx(Header, { title: "Linked virtual hosts" }) }), children] }));
9
+ };
10
+ /**
11
+ * Component to display the virtual hosts linked to an app installation. There
12
+ * is no specific API endpoint to fetch this information, so we have to fetch
13
+ * all virtual hosts and filter them by the installation ID.
14
+ *
15
+ * @class
16
+ * @param appInstallation
17
+ */
18
+ export const AppVirtualHosts = ({ appInstallation }) => {
19
+ const virtualHosts = maybe(useVirtualHosts)(appInstallation.projectId);
20
+ if (!virtualHosts || virtualHosts.length === 0) {
21
+ return (_jsx(AppVirtualHostBox, { children: _jsx(Text, { children: "No virtual hosts are linked to this app installation" }) }));
22
+ }
23
+ const matchingURLs = buildAppURLsFromIngressList(virtualHosts, appInstallation.id);
24
+ return (_jsx(AppVirtualHostBox, { children: matchingURLs.map((url, idx) => (_jsx(Text, { children: url }, idx))) }));
25
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mittwald/cli",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.1.0",
4
4
  "description": "Hand-crafted CLI for the mittwald API",
5
5
  "license": "MIT",
6
6
  "author": {