@mittwald/cli 1.5.0 → 1.6.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/dist/commands/app/dependency/list.d.ts +1 -0
- package/dist/commands/app/dependency/versions.d.ts +1 -0
- package/dist/commands/app/get.js +1 -2
- package/dist/commands/app/list-upgrade-candidates.d.ts +1 -0
- package/dist/commands/app/list.d.ts +1 -0
- package/dist/commands/backup/delete.d.ts +1 -0
- package/dist/commands/backup/get.js +1 -2
- package/dist/commands/backup/list.d.ts +1 -0
- package/dist/commands/backup/schedule/list.d.ts +1 -0
- package/dist/commands/container/delete.d.ts +1 -0
- package/dist/commands/container/list.d.ts +1 -0
- package/dist/commands/container/logs.d.ts +1 -0
- package/dist/commands/container/run.d.ts +0 -16
- package/dist/commands/container/run.js +4 -61
- package/dist/commands/container/update.d.ts +36 -0
- package/dist/commands/container/update.js +174 -0
- package/dist/commands/conversation/categories.d.ts +1 -0
- package/dist/commands/conversation/create.d.ts +1 -0
- package/dist/commands/conversation/list.d.ts +1 -0
- package/dist/commands/conversation/reply.d.ts +1 -0
- package/dist/commands/cronjob/delete.d.ts +1 -0
- package/dist/commands/cronjob/execution/get.d.ts +1 -1
- package/dist/commands/cronjob/execution/list.d.ts +1 -0
- package/dist/commands/cronjob/execution/logs.d.ts +1 -0
- package/dist/commands/cronjob/get.js +1 -2
- package/dist/commands/cronjob/list.d.ts +1 -0
- package/dist/commands/database/list.d.ts +1 -0
- package/dist/commands/database/mysql/charsets.d.ts +1 -0
- package/dist/commands/database/mysql/delete.d.ts +1 -0
- package/dist/commands/database/mysql/get.d.ts +1 -1
- package/dist/commands/database/mysql/list.d.ts +1 -0
- package/dist/commands/database/mysql/user/delete.d.ts +1 -0
- package/dist/commands/database/mysql/user/get.d.ts +1 -1
- package/dist/commands/database/mysql/user/list.d.ts +1 -0
- package/dist/commands/database/mysql/versions.d.ts +1 -0
- package/dist/commands/database/redis/get.d.ts +1 -1
- package/dist/commands/database/redis/list.d.ts +1 -0
- package/dist/commands/database/redis/versions.d.ts +1 -0
- package/dist/commands/domain/dnszone/get.js +1 -2
- package/dist/commands/domain/dnszone/list.d.ts +1 -0
- package/dist/commands/domain/get.js +1 -2
- package/dist/commands/domain/list.d.ts +1 -0
- package/dist/commands/domain/virtualhost/delete.d.ts +1 -0
- package/dist/commands/domain/virtualhost/get.js +1 -2
- package/dist/commands/domain/virtualhost/list.d.ts +1 -0
- package/dist/commands/extension/list-installed.d.ts +1 -0
- package/dist/commands/extension/list.d.ts +1 -0
- package/dist/commands/mail/address/create.d.ts +2 -1
- package/dist/commands/mail/address/create.js +2 -1
- package/dist/commands/mail/address/delete.d.ts +1 -0
- package/dist/commands/mail/address/get.d.ts +1 -1
- package/dist/commands/mail/address/list.d.ts +1 -0
- package/dist/commands/mail/deliverybox/delete.d.ts +1 -0
- package/dist/commands/mail/deliverybox/get.d.ts +1 -1
- package/dist/commands/mail/deliverybox/list.d.ts +1 -0
- package/dist/commands/org/delete.d.ts +1 -0
- package/dist/commands/org/get.js +1 -2
- package/dist/commands/org/invite/list-own.d.ts +1 -0
- package/dist/commands/org/invite/list.d.ts +1 -0
- package/dist/commands/org/list.d.ts +1 -0
- package/dist/commands/org/membership/list-own.d.ts +4 -0
- package/dist/commands/org/membership/list.d.ts +4 -0
- package/dist/commands/project/delete.d.ts +1 -0
- package/dist/commands/project/filesystem/usage.js +1 -2
- package/dist/commands/project/get.js +1 -2
- package/dist/commands/project/invite/get.d.ts +1 -1
- package/dist/commands/project/invite/list-own.d.ts +1 -0
- package/dist/commands/project/invite/list.d.ts +1 -0
- package/dist/commands/project/list.d.ts +1 -0
- package/dist/commands/project/membership/get-own.d.ts +1 -0
- package/dist/commands/project/membership/get.d.ts +1 -1
- package/dist/commands/project/membership/list-own.d.ts +1 -0
- package/dist/commands/project/membership/list.d.ts +1 -0
- package/dist/commands/registry/delete.d.ts +1 -0
- package/dist/commands/registry/list.d.ts +1 -0
- package/dist/commands/server/get.d.ts +1 -1
- package/dist/commands/server/list.d.ts +1 -0
- package/dist/commands/sftp-user/delete.d.ts +1 -0
- package/dist/commands/sftp-user/list.d.ts +1 -0
- package/dist/commands/ssh-user/delete.d.ts +1 -0
- package/dist/commands/ssh-user/list.d.ts +1 -0
- package/dist/commands/stack/delete.d.ts +1 -0
- package/dist/commands/stack/deploy.js +1 -8
- package/dist/commands/stack/list.d.ts +1 -0
- package/dist/commands/stack/ps.d.ts +1 -0
- package/dist/commands/stack/ps.js +1 -1
- package/dist/commands/user/api-token/get.d.ts +1 -1
- package/dist/commands/user/api-token/list.d.ts +1 -0
- package/dist/commands/user/api-token/revoke.d.ts +1 -0
- package/dist/commands/user/get.d.ts +1 -1
- package/dist/commands/user/session/get.d.ts +1 -1
- package/dist/commands/user/session/list.d.ts +1 -0
- package/dist/commands/user/ssh-key/delete.d.ts +1 -0
- package/dist/commands/user/ssh-key/get.d.ts +1 -1
- package/dist/commands/user/ssh-key/list.d.ts +1 -0
- package/dist/lib/basecommands/BaseCommand.d.ts +7 -5
- package/dist/lib/basecommands/BaseCommand.js +25 -8
- package/dist/lib/basecommands/CommandFlags.d.ts +3 -3
- package/dist/lib/basecommands/CoreBaseCommand.d.ts +12 -0
- package/dist/lib/basecommands/CoreBaseCommand.js +16 -0
- package/dist/lib/basecommands/DeleteBaseCommand.d.ts +1 -0
- package/dist/lib/basecommands/DeleteBaseCommand.js +1 -0
- package/dist/lib/basecommands/ExecRenderBaseCommand.d.ts +3 -0
- package/dist/lib/basecommands/ExecRenderBaseCommand.js +3 -0
- package/dist/lib/basecommands/ExtendedBaseCommand.d.ts +3 -0
- package/dist/lib/basecommands/ExtendedBaseCommand.js +3 -0
- package/dist/lib/basecommands/GetBaseCommand.d.ts +1 -1
- package/dist/lib/basecommands/GetBaseCommand.js +1 -0
- package/dist/lib/basecommands/ListBaseCommand.d.ts +1 -0
- package/dist/lib/basecommands/ListBaseCommand.js +1 -0
- package/dist/lib/basecommands/UnauthenticatedBaseCommand.d.ts +10 -0
- package/dist/lib/basecommands/UnauthenticatedBaseCommand.js +16 -0
- package/dist/lib/resources/container/containerconfig.d.ts +43 -0
- package/dist/lib/resources/container/containerconfig.js +82 -0
- package/dist/lib/resources/stack/enrich.d.ts +2 -2
- package/dist/lib/resources/stack/enrich.js +1 -31
- package/package.json +8 -8
|
@@ -4,7 +4,7 @@ type APIResponse = Awaited<ReturnType<MittwaldAPIV2Client["user"]["getApiToken"]
|
|
|
4
4
|
export default class Get extends GetBaseCommand<typeof Get, APIResponse> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
|
-
|
|
7
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
8
|
};
|
|
9
9
|
static args: {
|
|
10
10
|
"token-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -14,6 +14,7 @@ export default class List extends ListBaseCommand<typeof List, ResponseItem, Res
|
|
|
14
14
|
"no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
15
|
"no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
16
|
"csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
|
|
17
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
18
|
};
|
|
18
19
|
getData(): Promise<Response>;
|
|
19
20
|
protected getColumns(): ListColumns<ResponseItem>;
|
|
@@ -8,6 +8,7 @@ export default class Revoke extends DeleteBaseCommand<typeof Revoke> {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
};
|
|
12
13
|
protected deleteResource(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -5,7 +5,7 @@ type APIResponse = Awaited<ReturnType<MittwaldAPIV2Client["user"]["getUser"]>>;
|
|
|
5
5
|
export default class Get extends GetBaseCommand<typeof Get, APIResponse> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: {
|
|
8
|
-
|
|
8
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
};
|
|
10
10
|
static args: {
|
|
11
11
|
"user-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -4,7 +4,7 @@ type APIResponse = Awaited<ReturnType<MittwaldAPIV2Client["user"]["getSession"]>
|
|
|
4
4
|
export default class Get extends GetBaseCommand<typeof Get, APIResponse> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
|
-
|
|
7
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
8
|
};
|
|
9
9
|
static args: {
|
|
10
10
|
"token-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -14,6 +14,7 @@ export default class List extends ListBaseCommand<typeof List, ResponseItem, Res
|
|
|
14
14
|
"no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
15
|
"no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
16
|
"csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
|
|
17
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
18
|
};
|
|
18
19
|
getData(): Promise<Response>;
|
|
19
20
|
protected getColumns(): ListColumns<ResponseItem>;
|
|
@@ -8,6 +8,7 @@ export default class Delete extends DeleteBaseCommand<typeof Delete> {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
};
|
|
12
13
|
protected deleteResource(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -4,7 +4,7 @@ type APIResponse = Awaited<ReturnType<MittwaldAPIV2Client["user"]["getSshKey"]>>
|
|
|
4
4
|
export default class Get extends GetBaseCommand<typeof Get, APIResponse> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
|
-
|
|
7
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
8
|
};
|
|
9
9
|
static args: {
|
|
10
10
|
"key-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -15,6 +15,7 @@ export default class List extends ListBaseCommand<typeof List, ResponseItem, Res
|
|
|
15
15
|
"no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
16
|
"no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
17
|
"csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
|
|
18
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
19
|
};
|
|
19
20
|
getData(): Promise<Response>;
|
|
20
21
|
protected mapData(data: SuccessfulResponse<Response, 200>["data"]): MittwaldAPIV2.Components.Schemas.SignupSshKey[];
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare abstract class BaseCommand extends
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { CoreBaseCommand } from "./CoreBaseCommand.js";
|
|
2
|
+
/** Base command class for authenticated commands that includes the --token flag. */
|
|
3
|
+
export declare abstract class BaseCommand extends CoreBaseCommand {
|
|
4
|
+
static baseFlags: {
|
|
5
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
};
|
|
6
7
|
init(): Promise<void>;
|
|
8
|
+
private getEffectiveTokenWithFlag;
|
|
7
9
|
}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
2
|
import { MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
3
|
-
import { configureAxiosRetry } from "../apiutil/api_retry.js";
|
|
4
|
-
import { configureConsistencyHandling } from "../apiutil/api_consistency.js";
|
|
5
3
|
import { getTokenFilename, readApiToken } from "../auth/token.js";
|
|
4
|
+
import { CoreBaseCommand } from "./CoreBaseCommand.js";
|
|
6
5
|
import { configureAxiosLogging } from "../apiutil/api_logging.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import { configureAxiosRetry } from "../apiutil/api_retry.js";
|
|
7
|
+
import { configureConsistencyHandling } from "../apiutil/api_consistency.js";
|
|
8
|
+
/** Base command class for authenticated commands that includes the --token flag. */
|
|
9
|
+
export class BaseCommand extends CoreBaseCommand {
|
|
10
|
+
static baseFlags = {
|
|
11
|
+
token: Flags.string({
|
|
12
|
+
description: "API token to use for authentication (overrides environment and config file). NOTE: watch out that tokens passed via this flag might be logged in your shell history.",
|
|
13
|
+
required: false,
|
|
14
|
+
helpGroup: "AUTHENTICATION",
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
10
17
|
async init() {
|
|
11
18
|
await super.init();
|
|
19
|
+
// Override the parent's auth behavior to include --token flag support
|
|
12
20
|
if (this.authenticationRequired) {
|
|
13
|
-
const
|
|
21
|
+
const { flags } = await this.parse();
|
|
22
|
+
const token = await this.getEffectiveTokenWithFlag(flags);
|
|
14
23
|
if (token === undefined) {
|
|
15
|
-
throw new Error(`Could not get token from
|
|
24
|
+
throw new Error(`Could not get token from --token flag, MITTWALD_API_TOKEN env var, or config file (${getTokenFilename(this.config)}). Please run "mw login token" or use --token.`);
|
|
16
25
|
}
|
|
17
26
|
this.apiClient = MittwaldAPIV2Client.newWithToken(token);
|
|
18
27
|
this.apiClient.axios.defaults.headers["User-Agent"] =
|
|
@@ -22,4 +31,12 @@ export class BaseCommand extends Command {
|
|
|
22
31
|
configureConsistencyHandling(this.apiClient.axios);
|
|
23
32
|
}
|
|
24
33
|
}
|
|
34
|
+
async getEffectiveTokenWithFlag(flags) {
|
|
35
|
+
// 1. Check --token flag first (highest precedence)
|
|
36
|
+
if (flags.token) {
|
|
37
|
+
return flags.token;
|
|
38
|
+
}
|
|
39
|
+
// 2. Fall back to existing readApiToken logic (env then file)
|
|
40
|
+
return await readApiToken(this.config);
|
|
41
|
+
}
|
|
25
42
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CoreBaseCommand } from "./CoreBaseCommand.js";
|
|
2
2
|
import { Interfaces } from "@oclif/core";
|
|
3
3
|
/** CommandFlags is a helper type that extracts the flags from a command class. */
|
|
4
|
-
export type CommandFlags<T extends typeof
|
|
4
|
+
export type CommandFlags<T extends typeof CoreBaseCommand> = Interfaces.InferredFlags<T["flags"]>;
|
|
5
5
|
/** CommandArgs is a helper type that extracts the args from a command class. */
|
|
6
|
-
export type CommandArgs<T extends typeof
|
|
6
|
+
export type CommandArgs<T extends typeof CoreBaseCommand> = Interfaces.InferredArgs<T["args"]>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import { MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
3
|
+
/**
|
|
4
|
+
* Core base command class that provides common functionality but no
|
|
5
|
+
* authentication flags. This is the base for both authenticated and
|
|
6
|
+
* unauthenticated command hierarchies.
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class CoreBaseCommand extends Command {
|
|
9
|
+
protected authenticationRequired: boolean;
|
|
10
|
+
protected apiClient: MittwaldAPIV2Client;
|
|
11
|
+
protected getEffectiveToken(): Promise<string | undefined>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import { MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
3
|
+
import { readApiToken } from "../auth/token.js";
|
|
4
|
+
/**
|
|
5
|
+
* Core base command class that provides common functionality but no
|
|
6
|
+
* authentication flags. This is the base for both authenticated and
|
|
7
|
+
* unauthenticated command hierarchies.
|
|
8
|
+
*/
|
|
9
|
+
export class CoreBaseCommand extends Command {
|
|
10
|
+
authenticationRequired = true;
|
|
11
|
+
apiClient = MittwaldAPIV2Client.newUnauthenticated();
|
|
12
|
+
async getEffectiveToken() {
|
|
13
|
+
// Only check env and file - no --token flag in this base class
|
|
14
|
+
return await readApiToken(this.config);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -5,6 +5,7 @@ export declare abstract class DeleteBaseCommand<T extends typeof BaseCommand> ex
|
|
|
5
5
|
static baseFlags: {
|
|
6
6
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
9
|
};
|
|
9
10
|
protected exec(): Promise<void>;
|
|
10
11
|
protected render(): null;
|
|
@@ -2,6 +2,9 @@ import { BaseCommand } from "./BaseCommand.js";
|
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
|
|
4
4
|
export declare abstract class ExecRenderBaseCommand<T extends typeof BaseCommand, TRes> extends ExtendedBaseCommand<T> {
|
|
5
|
+
static baseFlags: {
|
|
6
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
5
8
|
protected abstract exec(): Promise<TRes>;
|
|
6
9
|
run(): Promise<void>;
|
|
7
10
|
protected abstract render(executionResult: TRes): ReactNode;
|
|
@@ -14,6 +14,9 @@ function wrapRender(fn) {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
export class ExecRenderBaseCommand extends ExtendedBaseCommand {
|
|
17
|
+
static baseFlags = {
|
|
18
|
+
...ExtendedBaseCommand.baseFlags,
|
|
19
|
+
};
|
|
17
20
|
async run() {
|
|
18
21
|
const result = await this.exec();
|
|
19
22
|
const wrappedRender = wrapRender(this.render.bind(this));
|
|
@@ -2,6 +2,9 @@ import { BaseCommand } from "./BaseCommand.js";
|
|
|
2
2
|
import { CommandArgs, CommandFlags } from "./CommandFlags.js";
|
|
3
3
|
import { CommandType } from "../context/FlagSetBuilder.js";
|
|
4
4
|
export declare abstract class ExtendedBaseCommand<T extends typeof BaseCommand> extends BaseCommand {
|
|
5
|
+
static baseFlags: {
|
|
6
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
5
8
|
protected flags: CommandFlags<T>;
|
|
6
9
|
protected args: CommandArgs<T>;
|
|
7
10
|
init(): Promise<void>;
|
|
@@ -4,6 +4,9 @@ import { withProjectId } from "../resources/project/flags.js";
|
|
|
4
4
|
import { withServerId } from "../resources/server/flags.js";
|
|
5
5
|
import { withStackId } from "../resources/stack/flags.js";
|
|
6
6
|
export class ExtendedBaseCommand extends BaseCommand {
|
|
7
|
+
static baseFlags = {
|
|
8
|
+
...BaseCommand.baseFlags,
|
|
9
|
+
};
|
|
7
10
|
flags;
|
|
8
11
|
args;
|
|
9
12
|
async init() {
|
|
@@ -7,7 +7,7 @@ export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof G
|
|
|
7
7
|
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T["args"]>;
|
|
8
8
|
export declare abstract class GetBaseCommand<T extends typeof BaseCommand, TAPIResponse extends Response> extends ExtendedBaseCommand<T> {
|
|
9
9
|
static baseFlags: {
|
|
10
|
-
|
|
10
|
+
token: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
11
11
|
};
|
|
12
12
|
protected formatter: GetFormatter;
|
|
13
13
|
init(): Promise<void>;
|
|
@@ -3,6 +3,7 @@ import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
|
|
|
3
3
|
import { GetFormatter } from "../../rendering/formatter/GetFormatter.js";
|
|
4
4
|
export class GetBaseCommand extends ExtendedBaseCommand {
|
|
5
5
|
static baseFlags = {
|
|
6
|
+
...ExtendedBaseCommand.baseFlags,
|
|
6
7
|
...GetFormatter.flags,
|
|
7
8
|
};
|
|
8
9
|
formatter = new GetFormatter();
|
|
@@ -19,6 +19,7 @@ export declare abstract class ListBaseCommand<T extends typeof BaseCommand, TIte
|
|
|
19
19
|
"no-truncate": Interfaces.BooleanFlag<boolean>;
|
|
20
20
|
"no-relative-dates": Interfaces.BooleanFlag<boolean>;
|
|
21
21
|
"csv-separator": Interfaces.OptionFlag<"," | ";">;
|
|
22
|
+
token: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
22
23
|
};
|
|
23
24
|
protected formatter: ListFormatter;
|
|
24
25
|
protected sorter?: SorterFunction<TItem>;
|
|
@@ -4,6 +4,7 @@ import { ExtendedBaseCommand } from "./ExtendedBaseCommand.js";
|
|
|
4
4
|
import ListDateColumnFormatter, { isResourceWithCreatedAt, } from "../../rendering/formatter/ListDateColumnFormatter.js";
|
|
5
5
|
export class ListBaseCommand extends ExtendedBaseCommand {
|
|
6
6
|
static baseFlags = {
|
|
7
|
+
...ExtendedBaseCommand.baseFlags,
|
|
7
8
|
...ListFormatter.flags,
|
|
8
9
|
};
|
|
9
10
|
formatter = new ListFormatter();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CoreBaseCommand } from "./CoreBaseCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* Base command class for commands that do not require authentication. This
|
|
4
|
+
* class extends CoreBaseCommand directly, bypassing the --token flag from
|
|
5
|
+
* BaseCommand.
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class UnauthenticatedBaseCommand extends CoreBaseCommand {
|
|
8
|
+
protected authenticationRequired: boolean;
|
|
9
|
+
init(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CoreBaseCommand } from "./CoreBaseCommand.js";
|
|
2
|
+
import { MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
3
|
+
/**
|
|
4
|
+
* Base command class for commands that do not require authentication. This
|
|
5
|
+
* class extends CoreBaseCommand directly, bypassing the --token flag from
|
|
6
|
+
* BaseCommand.
|
|
7
|
+
*/
|
|
8
|
+
export class UnauthenticatedBaseCommand extends CoreBaseCommand {
|
|
9
|
+
// No baseFlags defined - we don't want the --token flag for these commands
|
|
10
|
+
authenticationRequired = false;
|
|
11
|
+
async init() {
|
|
12
|
+
await super.init();
|
|
13
|
+
// For unauthenticated commands, keep the unauthenticated API client
|
|
14
|
+
this.apiClient = this.apiClient || MittwaldAPIV2Client.newUnauthenticated();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { MittwaldAPIV2, MittwaldAPIV2Client } from "@mittwald/api-client";
|
|
2
|
+
type ContainerContainerImageConfig = MittwaldAPIV2.Components.Schemas.ContainerContainerImageConfig;
|
|
3
|
+
/**
|
|
4
|
+
* Parses environment variables from command line flags and env files
|
|
5
|
+
*
|
|
6
|
+
* @param envFlags Array of environment variable strings in KEY=VALUE format
|
|
7
|
+
* @param envFiles Array of paths to env files
|
|
8
|
+
* @returns An object containing environment variable key-value pairs
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseEnvironmentVariables(envFlags?: string[], envFiles?: string[]): Promise<Record<string, string>>;
|
|
11
|
+
/**
|
|
12
|
+
* Parses environment variables from env files
|
|
13
|
+
*
|
|
14
|
+
* @param envFiles Array of paths to env files
|
|
15
|
+
* @returns An object containing environment variable key-value pairs
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseEnvironmentVariablesFromFile(envFiles?: string[]): Promise<Record<string, string>>;
|
|
18
|
+
/**
|
|
19
|
+
* Parses environment variables from command line flags
|
|
20
|
+
*
|
|
21
|
+
* @param envFlags Array of environment variable strings in KEY=VALUE format
|
|
22
|
+
* @returns An object containing environment variable key-value pairs
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseEnvironmentVariablesFromEnvFlags(envFlags?: string[]): Record<string, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Determines which ports to expose based on image metadata
|
|
27
|
+
*
|
|
28
|
+
* @param imageMeta Metadata about the container image
|
|
29
|
+
* @param publishAll Whether to publish all ports defined in the image
|
|
30
|
+
* @param publishPorts Array of port mappings specified by the user
|
|
31
|
+
* @returns An array of port mappings
|
|
32
|
+
*/
|
|
33
|
+
export declare function getPortMappings(imageMeta: ContainerContainerImageConfig, publishAll?: boolean, publishPorts?: string[]): string[];
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves metadata for a container image
|
|
36
|
+
*
|
|
37
|
+
* @param apiClient The API client instance
|
|
38
|
+
* @param image The container image reference
|
|
39
|
+
* @param projectId The project ID for credentials
|
|
40
|
+
* @returns Metadata about the container image
|
|
41
|
+
*/
|
|
42
|
+
export declare function getImageMeta(apiClient: MittwaldAPIV2Client, image: string, projectId: string): Promise<ContainerContainerImageConfig>;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { assertStatus, } from "@mittwald/api-client";
|
|
2
|
+
import * as fs from "fs/promises";
|
|
3
|
+
import { parse } from "envfile";
|
|
4
|
+
import { pathExists } from "../../util/fs/pathExists.js";
|
|
5
|
+
/**
|
|
6
|
+
* Parses environment variables from command line flags and env files
|
|
7
|
+
*
|
|
8
|
+
* @param envFlags Array of environment variable strings in KEY=VALUE format
|
|
9
|
+
* @param envFiles Array of paths to env files
|
|
10
|
+
* @returns An object containing environment variable key-value pairs
|
|
11
|
+
*/
|
|
12
|
+
export async function parseEnvironmentVariables(envFlags = [], envFiles = []) {
|
|
13
|
+
return {
|
|
14
|
+
...parseEnvironmentVariablesFromEnvFlags(envFlags),
|
|
15
|
+
...(await parseEnvironmentVariablesFromFile(envFiles)),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parses environment variables from env files
|
|
20
|
+
*
|
|
21
|
+
* @param envFiles Array of paths to env files
|
|
22
|
+
* @returns An object containing environment variable key-value pairs
|
|
23
|
+
*/
|
|
24
|
+
export async function parseEnvironmentVariablesFromFile(envFiles = []) {
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const envFile of envFiles) {
|
|
27
|
+
if (!(await pathExists(envFile))) {
|
|
28
|
+
throw new Error(`Env file not found: ${envFile}`);
|
|
29
|
+
}
|
|
30
|
+
const fileContent = await fs.readFile(envFile, { encoding: "utf-8" });
|
|
31
|
+
const parsed = parse(fileContent);
|
|
32
|
+
Object.assign(result, parsed);
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parses environment variables from command line flags
|
|
38
|
+
*
|
|
39
|
+
* @param envFlags Array of environment variable strings in KEY=VALUE format
|
|
40
|
+
* @returns An object containing environment variable key-value pairs
|
|
41
|
+
*/
|
|
42
|
+
export function parseEnvironmentVariablesFromEnvFlags(envFlags = []) {
|
|
43
|
+
const splitIntoKeyAndValue = (e) => e.split("=", 2);
|
|
44
|
+
return Object.fromEntries(envFlags.map(splitIntoKeyAndValue));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Determines which ports to expose based on image metadata
|
|
48
|
+
*
|
|
49
|
+
* @param imageMeta Metadata about the container image
|
|
50
|
+
* @param publishAll Whether to publish all ports defined in the image
|
|
51
|
+
* @param publishPorts Array of port mappings specified by the user
|
|
52
|
+
* @returns An array of port mappings
|
|
53
|
+
*/
|
|
54
|
+
export function getPortMappings(imageMeta, publishAll = false, publishPorts = []) {
|
|
55
|
+
if (publishAll) {
|
|
56
|
+
const definedPorts = imageMeta.exposedPorts ?? [];
|
|
57
|
+
const concatPort = (p) => {
|
|
58
|
+
const [port, protocol = "tcp"] = p.port.split("/", 2);
|
|
59
|
+
return `${port}:${port}/${protocol}`;
|
|
60
|
+
};
|
|
61
|
+
return definedPorts.map(concatPort);
|
|
62
|
+
}
|
|
63
|
+
return publishPorts;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Retrieves metadata for a container image
|
|
67
|
+
*
|
|
68
|
+
* @param apiClient The API client instance
|
|
69
|
+
* @param image The container image reference
|
|
70
|
+
* @param projectId The project ID for credentials
|
|
71
|
+
* @returns Metadata about the container image
|
|
72
|
+
*/
|
|
73
|
+
export async function getImageMeta(apiClient, image, projectId) {
|
|
74
|
+
const resp = await apiClient.container.getContainerImageConfig({
|
|
75
|
+
queryParameters: {
|
|
76
|
+
imageReference: image,
|
|
77
|
+
useCredentialsForProjectId: projectId,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
assertStatus(resp, 200);
|
|
81
|
+
return resp.data;
|
|
82
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type MittwaldAPIV2
|
|
1
|
+
import { type MittwaldAPIV2 } from "@mittwald/api-client";
|
|
2
2
|
type StackRequest = MittwaldAPIV2.Paths.V2StacksStackId.Put.Parameters.RequestBody;
|
|
3
|
-
export declare function enrichStackDefinition(
|
|
3
|
+
export declare function enrichStackDefinition(input: StackRequest): Promise<StackRequest>;
|
|
4
4
|
export {};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { assertStatus, } from "@mittwald/api-client";
|
|
2
1
|
import { readFile } from "fs/promises";
|
|
3
2
|
import { parse } from "envfile";
|
|
4
|
-
export async function enrichStackDefinition(
|
|
3
|
+
export async function enrichStackDefinition(input) {
|
|
5
4
|
const enriched = structuredClone(input);
|
|
6
5
|
for (const serviceName of Object.keys(input.services ?? {})) {
|
|
7
6
|
let service = enriched.services[serviceName];
|
|
8
|
-
service = await setCommandAndEntrypointFromImage(apiClient, projectId, service);
|
|
9
7
|
service = await setEnvironmentFromEnvFile(service);
|
|
10
8
|
enriched.services[serviceName] = service;
|
|
11
9
|
}
|
|
@@ -25,31 +23,3 @@ async function setEnvironmentFromEnvFile(service) {
|
|
|
25
23
|
};
|
|
26
24
|
return enriched;
|
|
27
25
|
}
|
|
28
|
-
async function setCommandAndEntrypointFromImage(apiClient, projectId, service) {
|
|
29
|
-
const enriched = structuredClone(service);
|
|
30
|
-
const resp = await apiClient.container.getContainerImageConfig({
|
|
31
|
-
queryParameters: {
|
|
32
|
-
imageReference: service.image,
|
|
33
|
-
useCredentialsForProjectId: projectId,
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
assertStatus(resp, 200);
|
|
37
|
-
if (service.ports === undefined) {
|
|
38
|
-
enriched.ports = (resp.data.exposedPorts ?? []).map((p) => p.port);
|
|
39
|
-
}
|
|
40
|
-
if (service.command === undefined) {
|
|
41
|
-
let command = resp.data.command;
|
|
42
|
-
if (typeof command === "string") {
|
|
43
|
-
command = [command];
|
|
44
|
-
}
|
|
45
|
-
enriched.command = command;
|
|
46
|
-
}
|
|
47
|
-
if (service.entrypoint === undefined) {
|
|
48
|
-
let entrypoint = resp.data.entrypoint;
|
|
49
|
-
if (typeof entrypoint === "string") {
|
|
50
|
-
entrypoint = [entrypoint];
|
|
51
|
-
}
|
|
52
|
-
enriched.entrypoint = entrypoint;
|
|
53
|
-
}
|
|
54
|
-
return enriched;
|
|
55
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mittwald/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Hand-crafted CLI for the mittwald API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"type": "module",
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=
|
|
19
|
+
"node": ">=20.0.0"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"clean": "(rimraf --glob dist tsconfig.*.tsbuildinfo) | true",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"marked-terminal": "^7.3.0",
|
|
63
63
|
"open": "^10.0.3",
|
|
64
64
|
"parse-duration": "^2.0.1",
|
|
65
|
-
"pretty-bytes": "^
|
|
65
|
+
"pretty-bytes": "^7.0.0",
|
|
66
66
|
"react": "^18.2.0",
|
|
67
67
|
"semver": "^7.5.4",
|
|
68
68
|
"semver-parser": "^4.1.6",
|
|
@@ -73,10 +73,10 @@
|
|
|
73
73
|
"uuid": "^11.0.3"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@jest/globals": "^
|
|
76
|
+
"@jest/globals": "^30.0.4",
|
|
77
77
|
"@oclif/test": "^4.0.4",
|
|
78
78
|
"@types/js-yaml": "^4.0.9",
|
|
79
|
-
"@types/node": "^
|
|
79
|
+
"@types/node": "^24.0.10",
|
|
80
80
|
"@types/react": "^18",
|
|
81
81
|
"@types/semver": "^7.5.0",
|
|
82
82
|
"@types/shell-escape": "^0.2.3",
|
|
@@ -88,11 +88,11 @@
|
|
|
88
88
|
"eslint-plugin-json": "^4.0.1",
|
|
89
89
|
"eslint-plugin-prettier": "^5.5.1",
|
|
90
90
|
"globals": "^16.0.0",
|
|
91
|
-
"jest": "^
|
|
91
|
+
"jest": "^30.0.4",
|
|
92
92
|
"license-checker-rseidelsohn": "^4.2.6",
|
|
93
93
|
"nock": "^14.0.0",
|
|
94
94
|
"oclif": "^4.14.31",
|
|
95
|
-
"prettier": "~3.
|
|
95
|
+
"prettier": "~3.6.2",
|
|
96
96
|
"prettier-plugin-jsdoc": "^1.3.2",
|
|
97
97
|
"prettier-plugin-package": "^1.4.0",
|
|
98
98
|
"prettier-plugin-sort-json": "^4.1.1",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
],
|
|
224
224
|
"update": {
|
|
225
225
|
"node": {
|
|
226
|
-
"version": "
|
|
226
|
+
"version": "20.19.3"
|
|
227
227
|
},
|
|
228
228
|
"s3": {
|
|
229
229
|
"xz": true,
|