Refactored configuration loading function.

This commit is contained in:
2026-03-07 15:18:46 +01:00
parent 67dd2045e3
commit aa6f9e24f8
9 changed files with 63 additions and 71 deletions

1
src/cli/commands/auth.ts Normal file
View File

@@ -0,0 +1 @@
// SPDX-License-Identifier: MIT

View File

@@ -2,7 +2,7 @@
import { acquireResourceTokenFromLogin } from "../../azure/index.ts";
import { getDevOpsApiToken } from "../../devops/index.ts";
import { loadPublicConfig } from "../../index.ts";
import { loadConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -19,13 +19,7 @@ export async function runGetTokenCommand(values: CommandValues): Promise<unknown
throw new Error("--type is required for get-token (allowed: azurerm, devops)");
}
const config = await loadPublicConfig();
if (!config.tenantId) {
throw new Error("tenantId is required");
}
if (!config.clientId) {
throw new Error("clientId is required");
}
const config = await loadConfig("public-config");
if (tokenType === "azurerm") {
const result = await acquireResourceTokenFromLogin({

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
import { login } from "../../azure/index.ts";
import { loadPublicConfig } from "../../index.ts";
import { loadConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -17,7 +17,7 @@ Options:
}
export async function runLoginCommand(values: CommandValues): Promise<unknown> {
const config = await loadPublicConfig();
const config = await loadConfig("public-config");
return login({
tenantId: config.tenantId,
clientId: config.clientId,

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
import { logout } from "../../azure/index.ts";
import { loadPublicConfig } from "../../index.ts";
import { loadConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -13,7 +13,7 @@ Options:
}
export async function runLogoutCommand(values: CommandValues): Promise<unknown> {
const config = await loadPublicConfig();
const config = await loadConfig("public-config");
return logout({
tenantId: config.tenantId,
clientId: config.clientId,

View File

@@ -2,7 +2,7 @@
import { acquireResourceTokenFromLogin } from "../../azure/index.ts";
import { getDevOpsApiToken } from "../../devops/index.ts";
import { loadPublicConfig } from "../../index.ts";
import { loadConfig } from "../../index.ts";
import type { CommandValues } from "./types.ts";
@@ -54,13 +54,7 @@ async function getAutoAuthorizationHeader(url: URL): Promise<string | null> {
return null;
}
const config = await loadPublicConfig();
if (!config.tenantId) {
throw new Error("tenantId is required");
}
if (!config.clientId) {
throw new Error("clientId is required");
}
const config = await loadConfig("public-config");
if (host === "management.azure.com") {
const result = await acquireResourceTokenFromLogin({

View File

@@ -2,7 +2,7 @@
import { minimatch } from "minimatch";
import { loadPublicConfig } from "../../index.ts";
import { loadConfig } from "../../index.ts";
import { getGraphClient } from "../../graph/auth.ts";
type PermissionRow = {
@@ -28,7 +28,7 @@ export function filterByDisplayName<T extends DisplayNameRow>(rows: T[], pattern
}
export async function getGraphClientFromPublicConfig(): Promise<{ client: any }> {
const config = await loadPublicConfig();
const config = await loadConfig("public-config");
return getGraphClient({
tenantId: config.tenantId,
clientId: config.clientId,

View File

@@ -1,58 +1,36 @@
// SPDX-License-Identifier: MIT
import { readFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { validate as validateUuid } from "uuid";
import { getConfig } from "@slawek/sk-tools";
type Config = {
tenantId?: string;
clientId?: string;
tenantId: string;
clientId: string;
};
type ConfigCandidate = {
tenantId?: unknown;
clientId?: unknown;
};
export function getUserConfigDir(): string {
if (process.platform === "win32") {
return process.env.LOCALAPPDATA ?? path.join(os.homedir(), "AppData", "Local");
}
return process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config");
}
async function loadConfig(configFileName: string): Promise<Config> {
if (typeof configFileName !== "string" || configFileName.trim() === "") {
export async function loadConfig(configName: string): Promise<Config> {
if (typeof configName !== "string" || configName.trim() === "") {
throw new Error(
'Invalid config file name. Expected a non-empty string like "public-config.json" or "confidential-config.json".',
'Invalid config name. Expected a non-empty string like "public-config" or "confidential-config".',
);
}
const envConfig: Config = {
const envConfig = {
tenantId: process.env.AZURE_TENANT_ID,
clientId: process.env.AZURE_CLIENT_ID,
};
const configPath = path.join(getUserConfigDir(), "sk-az-tools", configFileName);
return readFile(configPath, "utf8")
.then((configJson) => JSON.parse(configJson) as ConfigCandidate)
.catch((err: unknown) => {
if ((err as { code?: string } | null)?.code === "ENOENT") {
return {} as ConfigCandidate;
}
throw err;
})
.then((json) => ({
tenantId: typeof json.tenantId === "string" && json.tenantId ? json.tenantId : envConfig.tenantId,
clientId: typeof json.clientId === "string" && json.clientId ? json.clientId : envConfig.clientId,
}));
}
const json = (await getConfig("sk-az-tools", configName)) as Record<string, unknown>;
export function loadPublicConfig(): Promise<Config> {
return loadConfig("public-config.json");
}
const tenantId = (typeof json.tenantId === "string" && json.tenantId ? json.tenantId : envConfig.tenantId) ?? "";
const clientId = (typeof json.clientId === "string" && json.clientId ? json.clientId : envConfig.clientId) ?? "";
export function loadConfidentialConfig(): Promise<Config> {
return loadConfig("confidential-config.json");
if (!validateUuid(tenantId ?? "") || !validateUuid(clientId ?? "")) {
throw new Error("tenantId and clientId must be valid GUIDs.");
}
return {
tenantId,
clientId,
};
}