Files
sk-az-tools/src/cli.js

142 lines
4.2 KiB
JavaScript
Executable File

#!/usr/bin/env node
// SPDX-License-Identifier: MIT
import { parseArgs } from "node:util";
import { runCommand } from "./cli/commands.js";
import {
normalizeOutputFormat,
omitPermissionGuidColumns,
outputFiltered,
parseHeaderSpec,
renderOutput,
} from "./cli/utils.js";
function usage() {
return `Usage: sk-az-tools <command> [options]
Commands:
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
table Render stdin JSON as Markdown table
Global options (all commands):
-q, --query <jmespath>
-o, --output <format> json|j|table|t|alignedtable|at|prettytable|pt
-h, --help
Use: sk-az-tools --help <command>
or: sk-az-tools <command> --help`;
}
function usageListApps() {
return `Usage: sk-az-tools list-apps [--display-name|-n <name>] [global options]
Options:
-n, --display-name <name> Filter apps by exact display name`;
}
function usageListAppPermissions() {
return `Usage: sk-az-tools list-app-permissions --app-id|-i <appId> [--resolve|-r] [--short|-s] [--filter|-f <glob>] [global options]
Options:
-i, --app-id <appId> Application (client) ID (required)
-r, --resolve Resolve permission GUIDs to human-readable values
-s, --short Makes output more compact
-f, --filter <glob> Filter by permission name glob`;
}
function usageListAppGrants() {
return `Usage: sk-az-tools list-app-grants --app-id|-i <appId> [global options]
Options:
-i, --app-id <appId> Application (client) ID (required)`;
}
function usageListResourcePermissions() {
return `Usage: sk-az-tools list-resource-permissions [--app-id|-i <appId> | --display-name|-n <name>] [--filter|-f <glob>] [global options]
Options:
-i, --app-id <appId> Resource app ID
-n, --display-name <name> Resource app display name
-f, --filter <glob> Filter by permission name glob`;
}
function usageTable() {
return `Usage: sk-az-tools table [--header|-H <spec|auto|a>] [global options]
Options:
-H, --header <value> Header mode/spec: auto|a OR "col1, col2" OR "key1: Label 1, key2: Label 2"`;
}
function usageCommand(command) {
switch (command) {
case "list-apps":
return usageListApps();
case "list-app-permissions":
return usageListAppPermissions();
case "list-app-grants":
return usageListAppGrants();
case "list-resource-permissions":
return usageListResourcePermissions();
case "table":
return usageTable();
default:
return `Unknown command: ${command}\n\n${usage()}`;
}
}
async function main() {
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" },
"display-name": { type: "string", short: "n" },
"app-id": { type: "string", short: "i" },
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,
});
if (values.help) {
console.log(usageCommand(command));
process.exit(0);
}
const outputFormat = normalizeOutputFormat(values.output);
const result = await runCommand(command, values);
const filtered = outputFiltered(result, values.query);
const output = command === "list-app-permissions" && values.short
? omitPermissionGuidColumns(filtered)
: filtered;
const headerSpec = parseHeaderSpec(values.header);
renderOutput(command, output, outputFormat, headerSpec);
}
main().catch((err) => {
console.error(`Error: ${err.message}`);
console.error(usage());
process.exit(1);
});