feat(cli): add graph commands with query and table output
This commit is contained in:
106
src/cli.js
Executable file
106
src/cli.js
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { parseArgs } from "node:util";
|
||||
import jmespath from "jmespath";
|
||||
|
||||
import { loadPublicConfig } from "./index.js";
|
||||
import { getGraphClient } from "./graph/auth.js";
|
||||
import { listApps, listAppPermissions, listAppGrants } from "./graph/app.js";
|
||||
import { toMarkdownTable } from "./markdown.js";
|
||||
|
||||
function usage() {
|
||||
return `Usage: sk-az-tools <command> [options]
|
||||
|
||||
Commands:
|
||||
list-apps [--display-name <name>]
|
||||
list-app-permissions --app-id <appId>
|
||||
list-app-grants --app-id <appId>
|
||||
|
||||
Options:
|
||||
--display-name <name> Filter apps by exact display name
|
||||
--app-id <appId> Application (client) ID
|
||||
--query <jmespath> Filter output JSON using JMESPath
|
||||
--output <format> Output format: json|table|prettytable (default: json)
|
||||
-h, --help Show this help message`;
|
||||
}
|
||||
|
||||
function outputFiltered(object, query) {
|
||||
return query
|
||||
? jmespath.search(object, query)
|
||||
: object;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const argv = process.argv.slice(2);
|
||||
const command = argv[0];
|
||||
if (command === "-h" || command === "--help") {
|
||||
console.log(usage());
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(1),
|
||||
options: {
|
||||
help: { type: "boolean", short: "h" },
|
||||
"display-name": { type: "string" },
|
||||
"app-id": { type: "string" },
|
||||
query: { type: "string" },
|
||||
output: { type: "string" },
|
||||
},
|
||||
strict: true,
|
||||
allowPositionals: false,
|
||||
});
|
||||
|
||||
if (values.help || !command) {
|
||||
console.log(usage());
|
||||
process.exit(0);
|
||||
}
|
||||
const outputFormat = values.output ?? "json";
|
||||
if (outputFormat !== "json" && outputFormat !== "table" && outputFormat !== "prettytable") {
|
||||
throw new Error("--output must be one of: json, table, prettytable");
|
||||
}
|
||||
|
||||
const config = await loadPublicConfig();
|
||||
const { client } = await getGraphClient({
|
||||
tenantId: config.tenantId,
|
||||
clientId: config.clientId,
|
||||
});
|
||||
|
||||
let result;
|
||||
switch (command) {
|
||||
case "list-apps":
|
||||
result = await listApps(client, {
|
||||
displayName: values["display-name"],
|
||||
});
|
||||
break;
|
||||
case "list-app-permissions":
|
||||
if (!values["app-id"]) {
|
||||
throw new Error("--app-id is required for list-app-permissions");
|
||||
}
|
||||
result = await listAppPermissions(client, values["app-id"]);
|
||||
break;
|
||||
case "list-app-grants":
|
||||
if (!values["app-id"]) {
|
||||
throw new Error("--app-id is required for list-app-grants");
|
||||
}
|
||||
result = await listAppGrants(client, values["app-id"]);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown command: ${command}`);
|
||||
}
|
||||
|
||||
const filtered = outputFiltered(result, values.query);
|
||||
if (outputFormat === "prettytable") {
|
||||
console.log(toMarkdownTable(filtered, true));
|
||||
} else if (outputFormat === "table") {
|
||||
console.log(toMarkdownTable(filtered));
|
||||
} else {
|
||||
console.log(JSON.stringify(filtered, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(`Error: ${err.message}`);
|
||||
console.error(usage());
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user