From 5265e5300c17fcb86466f4deee58f212f2cbe419 Mon Sep 17 00:00:00 2001 From: Slawomir Koszewski Date: Tue, 10 Mar 2026 19:48:02 +0100 Subject: [PATCH] refactor: remove unused usage functions and migrate argument parsing to commander.js --- src/cli.ts | 6 +- src/cli/commands/get-token.ts | 7 --- src/cli/commands/list-app-grants.ts | 7 --- src/cli/commands/list-app-permissions.ts | 10 ---- src/cli/commands/list-resource-permissions.ts | 9 --- src/cli/commands/login.ts | 11 ---- src/cli/commands/logout.ts | 7 --- src/cli/commands/types.ts | 19 ------- src/create-pca.ts | 55 ++++--------------- 9 files changed, 12 insertions(+), 119 deletions(-) delete mode 100644 src/cli/commands/types.ts diff --git a/src/cli.ts b/src/cli.ts index 9f87539..5d3045d 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: MIT import { Command, Option } from "commander"; -import { renderCliOutput} from "@slawek/sk-tools"; +import { renderCliOutput } from "@slawek/sk-tools"; // Commands import { runGetTokenCommand } from "./cli/commands/get-token.ts"; @@ -119,15 +119,11 @@ Authorization is added automatically for: const output = await runListResourcePermissionsCommand(options); renderCliOutput(output, skAzTools.opts().output, skAzTools.opts().query, skAzTools.opts().columns); }); - - - // Parse arguments await skAzTools.parseAsync(); } main().catch((err: unknown) => { const error = err as Error; console.error(`Error: ${error.message}`); - //console.error(usage()); process.exit(1); }); diff --git a/src/cli/commands/get-token.ts b/src/cli/commands/get-token.ts index 72d48e7..b851cb1 100644 --- a/src/cli/commands/get-token.ts +++ b/src/cli/commands/get-token.ts @@ -8,13 +8,6 @@ type GetTokenOptions = { type?: string; }; -export function usageGetToken(): string { - return `Usage: sk-az-tools get-token --type|-t [global options] - -Options: - --type, -t Token type: azurerm|devops`; -} - export async function runGetTokenCommand( options: GetTokenOptions, ): Promise { diff --git a/src/cli/commands/list-app-grants.ts b/src/cli/commands/list-app-grants.ts index 7aec1f2..2684324 100644 --- a/src/cli/commands/list-app-grants.ts +++ b/src/cli/commands/list-app-grants.ts @@ -7,13 +7,6 @@ type ListAppGrantsOptions = { appId?: string; }; -export function usageListAppGrants(): string { - return `Usage: sk-az-tools list-app-grants --app-id|-i [global options] - -Options: - --app-id, -i Application (client) ID (required)`; -} - export async function runListAppGrantsCommand(options: ListAppGrantsOptions): Promise { if (!options.appId) { throw new Error("--app-id is required for list-app-grants"); diff --git a/src/cli/commands/list-app-permissions.ts b/src/cli/commands/list-app-permissions.ts index 80f20bd..496e16b 100644 --- a/src/cli/commands/list-app-permissions.ts +++ b/src/cli/commands/list-app-permissions.ts @@ -29,16 +29,6 @@ function omitColumns(input: unknown, names: string[]): unknown { ); } -export function usageListAppPermissions(): string { - return `Usage: sk-az-tools list-app-permissions --app-id|-i [--resolve|-r] [--short|-s] [--filter|-f ] [global options] - -Options: - --app-id, -i Application (client) ID (required) - --resolve, -r Resolve permission GUIDs to human-readable values - --short, -s Makes output more compact - --filter, -f Filter by permission name glob`; -} - export async function runListAppPermissionsCommand(options: ListAppPermissionsOptions): Promise { if (!options.appId) { throw new Error("--app-id is required for list-app-permissions"); diff --git a/src/cli/commands/list-resource-permissions.ts b/src/cli/commands/list-resource-permissions.ts index 4a8b812..2a85d01 100644 --- a/src/cli/commands/list-resource-permissions.ts +++ b/src/cli/commands/list-resource-permissions.ts @@ -10,15 +10,6 @@ type ListResourcePermissionsOptions = { filter?: string; }; -export function usageListResourcePermissions(): string { - return `Usage: sk-az-tools list-resource-permissions [--app-id|-i | --display-name|-n ] [--filter|-f ] [global options] - -Options: - --app-id, -i Resource app ID - --display-name, -n Resource app display name - --filter, -f Filter by permission name glob`; -} - export async function runListResourcePermissionsCommand(options: ListResourcePermissionsOptions): Promise { if (!options.appId && !options.displayName) { throw new Error("--app-id or --display-name is required for list-resource-permissions"); diff --git a/src/cli/commands/login.ts b/src/cli/commands/login.ts index 999e6e7..298924d 100644 --- a/src/cli/commands/login.ts +++ b/src/cli/commands/login.ts @@ -11,17 +11,6 @@ type LoginOptions = { browserProfile?: string; }; -export function usageLogin(): string { - return `Usage: sk-az-tools login [--resources ] [--use-device-code] [--no-browser] [--browser ] [--browser-profile ] [global options] - -Options: - --resources Comma-separated resources: graph,devops,arm (default: all) - --use-device-code Use device code flow instead of interactive flow - --no-browser Do not launch browser; print interactive URL to stderr - --browser Browser keyword: brave|browser|browserPrivate|chrome|edge|firefox - --browser-profile Chromium profile name (e.g. Default, "Profile 1")`; -} - export async function runLoginCommand(options: LoginOptions): Promise { const config = await loadAuthConfig("public-config"); return login( diff --git a/src/cli/commands/logout.ts b/src/cli/commands/logout.ts index 4c23e78..d69765b 100644 --- a/src/cli/commands/logout.ts +++ b/src/cli/commands/logout.ts @@ -7,13 +7,6 @@ type LogoutOptions = { all?: boolean; }; -export function usageLogout(): string { - return `Usage: sk-az-tools logout [--all] [global options] - -Options: - --all Clear login state and remove all cached accounts`; -} - export async function runLogoutCommand(options: LogoutOptions): Promise { const config = await loadAuthConfig("public-config"); return logout(config.tenantId, config.clientId, Boolean(options.all)); diff --git a/src/cli/commands/types.ts b/src/cli/commands/types.ts deleted file mode 100644 index 6dabd1e..0000000 --- a/src/cli/commands/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT - -export type CommandValues = { - [key: string]: string | boolean | undefined; - type?: string; - method?: string; - url?: string; - header?: string; - resources?: string; - "use-device-code"?: boolean; - "no-browser"?: boolean; - browser?: string; - "browser-profile"?: string; - all?: boolean; - "display-name"?: string; - "app-id"?: string; - filter?: string; - resolve?: boolean; -}; diff --git a/src/create-pca.ts b/src/create-pca.ts index b0bb915..148217a 100644 --- a/src/create-pca.ts +++ b/src/create-pca.ts @@ -6,7 +6,7 @@ import os from "node:os"; import path from "node:path"; import readline from "node:readline"; import { spawnSync } from "node:child_process"; -import { parseArgs } from "node:util"; +import { Command } from "commander"; type RunAzResult = { status: number; @@ -40,50 +40,17 @@ function runAz(args: string[], quiet = false, allowFailure = false): RunAzResult } async function main(): Promise { - const usageText = `Usage: ${path.basename(process.argv[1])} [options] -Options: - -c, --config Write JSON config to file (optional) - -h, --help Show this help message and exit`; + const program = new Command(path.basename(process.argv[1])); + program + .description("Create or update public client app and print config template") + .argument("", "Application name") + .option("-c, --config ", "Write JSON config to file (optional)") + .allowExcessArguments(false) + .parse(process.argv); - let values: Record; - let positionals: string[]; - try { - ({ values, positionals } = parseArgs({ - args: process.argv.slice(2), - options: { - help: { type: "boolean", short: "h" }, - config: { type: "string", short: "c" }, - }, - strict: true, - allowPositionals: true, - })); - } catch (err) { - console.error(`Error: ${(err as Error).message}`); - console.error(usageText); - process.exit(1); - } - - if (values.help) { - console.log(usageText); - process.exit(0); - } - - if (positionals.length > 1) { - console.error( - "Error: Too many positional arguments. Only one app name positional argument is allowed.", - ); - console.error(usageText); - process.exit(1); - } - - const appName = positionals[0] || ""; - const configPath = typeof values.config === "string" ? values.config : ""; - - if (!appName) { - console.error("Error: Application name is required."); - console.error(usageText); - process.exit(1); - } + const appName = program.args[0] as string; + const options = program.opts<{ config?: string }>(); + const configPath = options.config ?? ""; let appId = runAz([ "ad",