#!/usr/bin/env node // SPDX-License-Identifier: MIT import { parseArgs } from "node:util"; import { runCommand } from "./cli/commands.ts"; import { usageGetToken } from "./cli/commands/get-token.ts"; import { usageListAppGrants } from "./cli/commands/list-app-grants.ts"; import { usageListAppPermissions } from "./cli/commands/list-app-permissions.ts"; import { usageListApps } from "./cli/commands/list-apps.ts"; import { usageListResourcePermissions } from "./cli/commands/list-resource-permissions.ts"; import { usageLogin } from "./cli/commands/login.ts"; import { usageLogout } from "./cli/commands/logout.ts"; import { usageRest } from "./cli/commands/rest.ts"; import { normalizeOutputFormat, outputFiltered, parseHeaderSpec, renderOutput, } from "@slawek/sk-tools"; import { omitPermissionGuidColumns, } from "./cli/permission-utils.ts"; type CliValues = { help?: boolean; type?: string; method?: string; url?: string; "display-name"?: string; "app-id"?: string; resources?: string; "use-device-code"?: boolean; "no-browser"?: boolean; browser?: string; "browser-profile"?: string; all?: boolean; resolve?: boolean; short?: boolean; filter?: string; query?: string; header?: string; output?: string; [key: string]: string | boolean | undefined; }; function usage(): string { return `Usage: sk-az-tools [options] Commands: login Authenticate selected resources logout Sign out and clear login state get-token Get access token (azurerm|devops) rest Call REST API endpoint list-apps List Entra applications list-app-permissions List required permissions for an app list-app-grants List OAuth2 grants for an app list-resource-permissions List available permissions for a resource app Global options (all commands): -q, --query -o, --output table|t|alignedtable|at|prettytable|pt|tsv -h, --help Use: sk-az-tools --help or: sk-az-tools --help`; } function usageCommand(command: string): string { switch (command) { case "login": return usageLogin(); case "list-apps": return usageListApps(); case "logout": return usageLogout(); case "get-token": return usageGetToken(); case "rest": return usageRest(); case "list-app-permissions": return usageListAppPermissions(); case "list-app-grants": return usageListAppGrants(); case "list-resource-permissions": return usageListResourcePermissions(); default: return `Unknown command: ${command}\n\n${usage()}`; } } async function main(): Promise { const argv = process.argv.slice(2); const command = argv[0]; if (!command) { console.log(usage()); process.exit(0); } if (command === "-h" || command === "--help") { const helpCommand = argv[1]; console.log(helpCommand ? usageCommand(helpCommand) : usage()); process.exit(0); } const { values } = parseArgs({ args: argv.slice(1), options: { help: { type: "boolean", short: "h" }, type: { type: "string", short: "t" }, method: { type: "string" }, url: { type: "string" }, "display-name": { type: "string", short: "n" }, "app-id": { type: "string", short: "i" }, resources: { type: "string" }, "use-device-code": { type: "boolean" }, "no-browser": { type: "boolean" }, browser: { type: "string" }, "browser-profile": { type: "string" }, all: { type: "boolean" }, resolve: { type: "boolean", short: "r" }, short: { type: "boolean", short: "s" }, filter: { type: "string", short: "f" }, query: { type: "string", short: "q" }, header: { type: "string", short: "H" }, output: { type: "string", short: "o" }, }, strict: true, allowPositionals: false, }); const typedValues = values as CliValues; if (typedValues.help) { console.log(usageCommand(command)); process.exit(0); } const outputFormat = normalizeOutputFormat(typedValues.output); const result = await runCommand(command, typedValues); const filtered = outputFiltered(result, typedValues.query); const output = command === "list-app-permissions" && typedValues.short ? omitPermissionGuidColumns(filtered) : filtered; const headerSpec = command === "rest" ? parseHeaderSpec(undefined) : parseHeaderSpec(typedValues.header); renderOutput(command, output, outputFormat, headerSpec); } main().catch((err: unknown) => { const error = err as Error; console.error(`Error: ${error.message}`); console.error(usage()); process.exit(1); });