azdo-cli 0.19.0-feature-040-auth-token.718 → 0.19.0-feature-040-auth-token.720
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Azure DevOps CLI focused on work item read/write workflows.
|
|
|
19
19
|
- Feed long PR titles, descriptions and comment bodies from a file or a pipe instead of the shell (`--title-file`, `--description-file`, `--file`; `-` reads standard input)
|
|
20
20
|
- Persist org/project/default fields in local config (`config`)
|
|
21
21
|
- List all fields of a work item (`list-fields`)
|
|
22
|
-
- Authenticate per Azure DevOps organization with `azdo auth login` — OAuth (Microsoft Entra) by default, or a Personal Access Token via `--use-pat` (or the `AZDO_PAT` env var). Credentials are stored in the OS credential store. Inspect with `azdo auth status`, remove with `azdo auth logout`. Diagnose auth problems with `azdo auth diagnose`. See [docs/authentication.md](docs/authentication.md).
|
|
22
|
+
- Authenticate per Azure DevOps organization with `azdo auth login` — OAuth (Microsoft Entra) by default, or a Personal Access Token via `--use-pat` (or the `AZDO_PAT` env var). Credentials are stored in the OS credential store. Inspect with `azdo auth status`, remove with `azdo auth logout`. Diagnose auth problems with `azdo auth diagnose`. Print the credential the CLI itself would use, for API calls the CLI does not yet wrap, with `azdo auth token`. See [docs/authentication.md](docs/authentication.md).
|
|
23
23
|
- Trace all HTTP requests to a local file with `--trace <filepath>` (sensitive headers and tokens are automatically redacted).
|
|
24
24
|
|
|
25
25
|
## Installation
|
|
@@ -825,10 +825,18 @@ function entryFor(account) {
|
|
|
825
825
|
return wrapUnavailable(() => new Entry(SERVICE, account));
|
|
826
826
|
}
|
|
827
827
|
var legacyUnsetNoticeEmitted = false;
|
|
828
|
+
var noticesSuppressed = false;
|
|
829
|
+
function suppressCredentialStoreNotices(suppressed) {
|
|
830
|
+
noticesSuppressed = suppressed;
|
|
831
|
+
}
|
|
832
|
+
function writeNotice(message) {
|
|
833
|
+
if (noticesSuppressed) return;
|
|
834
|
+
process.stderr.write(message);
|
|
835
|
+
}
|
|
828
836
|
function emitLegacyUnsetNoticeOnce() {
|
|
829
837
|
if (legacyUnsetNoticeEmitted) return;
|
|
830
838
|
legacyUnsetNoticeEmitted = true;
|
|
831
|
-
|
|
839
|
+
writeNotice(
|
|
832
840
|
'A legacy PAT exists in the OS vault from a previous azdo-cli version, but no "org" is set in config. Run `azdo auth --org <name>` to re-store it under the per-org key, then `azdo clear-pat` to remove the legacy slot.\n'
|
|
833
841
|
);
|
|
834
842
|
}
|
|
@@ -925,7 +933,7 @@ async function maybeMigrateLegacy(targetOrg) {
|
|
|
925
933
|
backend: probeBackend(),
|
|
926
934
|
masked_pat: maskedDisplay(legacy)
|
|
927
935
|
});
|
|
928
|
-
|
|
936
|
+
writeNotice(`Migrated legacy PAT to org ${targetOrg}.
|
|
929
937
|
`);
|
|
930
938
|
return legacy;
|
|
931
939
|
}
|
|
@@ -990,7 +998,7 @@ async function deletePat(org) {
|
|
|
990
998
|
}
|
|
991
999
|
try {
|
|
992
1000
|
const { unlinkSync: unlinkSync2 } = await import("fs");
|
|
993
|
-
const { lockPath: lockPath2 } = await import("./oauth-token-refresh-
|
|
1001
|
+
const { lockPath: lockPath2 } = await import("./oauth-token-refresh-PXUQE5JE.js");
|
|
994
1002
|
unlinkSync2(lockPath2(org));
|
|
995
1003
|
} catch {
|
|
996
1004
|
}
|
|
@@ -1212,6 +1220,7 @@ export {
|
|
|
1212
1220
|
refreshIfNeeded,
|
|
1213
1221
|
_resetInFlight,
|
|
1214
1222
|
probeBackend,
|
|
1223
|
+
suppressCredentialStoreNotices,
|
|
1215
1224
|
getPat,
|
|
1216
1225
|
getStoredCredential,
|
|
1217
1226
|
storePat,
|
package/dist/index.js
CHANGED
|
@@ -33,10 +33,11 @@ import {
|
|
|
33
33
|
setOrgScopedValue,
|
|
34
34
|
storeOAuthCredential,
|
|
35
35
|
storePat,
|
|
36
|
+
suppressCredentialStoreNotices,
|
|
36
37
|
tokenResponseToCredential,
|
|
37
38
|
unsetConfigValue,
|
|
38
39
|
unsetOrgScopedValue
|
|
39
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-K2CKMY72.js";
|
|
40
41
|
|
|
41
42
|
// src/index.ts
|
|
42
43
|
import { Command as Command19 } from "commander";
|
|
@@ -1166,28 +1167,28 @@ function findDotEnvPat(startDir = process.cwd()) {
|
|
|
1166
1167
|
return null;
|
|
1167
1168
|
}
|
|
1168
1169
|
async function resolveAuthCredential(org) {
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
if (stored.kind === "pat") {
|
|
1176
|
-
return { pat: stored.token, source: "credential-store", kind: "pat" };
|
|
1170
|
+
let cred;
|
|
1171
|
+
try {
|
|
1172
|
+
cred = await exportCredential(org);
|
|
1173
|
+
} catch (err) {
|
|
1174
|
+
if (err instanceof CredentialMissingError) {
|
|
1175
|
+
return null;
|
|
1177
1176
|
}
|
|
1178
|
-
|
|
1177
|
+
throw err;
|
|
1178
|
+
}
|
|
1179
|
+
if (cred.kind === "oauth") {
|
|
1179
1180
|
return {
|
|
1180
|
-
pat:
|
|
1181
|
+
pat: cred.token,
|
|
1181
1182
|
source: "credential-store",
|
|
1182
1183
|
kind: "oauth",
|
|
1183
|
-
accountId:
|
|
1184
|
+
accountId: cred.accountId
|
|
1184
1185
|
};
|
|
1185
1186
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1187
|
+
return {
|
|
1188
|
+
pat: cred.token,
|
|
1189
|
+
source: cred.source === "credential-store" ? "credential-store" : "env",
|
|
1190
|
+
kind: "pat"
|
|
1191
|
+
};
|
|
1191
1192
|
}
|
|
1192
1193
|
var lastResolvedCredential = null;
|
|
1193
1194
|
async function requireAuthCredential(org) {
|
|
@@ -2437,6 +2438,8 @@ async function handleToken(orgFromGlobal) {
|
|
|
2437
2438
|
return;
|
|
2438
2439
|
}
|
|
2439
2440
|
const org = resolved.org;
|
|
2441
|
+
const stderrIsTty = Boolean(process.stderr.isTTY);
|
|
2442
|
+
suppressCredentialStoreNotices(!stderrIsTty);
|
|
2440
2443
|
let cred;
|
|
2441
2444
|
try {
|
|
2442
2445
|
cred = await exportCredential(org);
|
|
@@ -2450,7 +2453,7 @@ async function handleToken(orgFromGlobal) {
|
|
|
2450
2453
|
backend: probeBackend(),
|
|
2451
2454
|
...cred.kind === "oauth" ? { accountId: cred.accountId } : {}
|
|
2452
2455
|
});
|
|
2453
|
-
if (
|
|
2456
|
+
if (stderrIsTty) {
|
|
2454
2457
|
process.stderr.write(describeExportedCredential(cred, org));
|
|
2455
2458
|
}
|
|
2456
2459
|
process.stdout.write(`${cred.token}
|
|
@@ -2540,7 +2543,9 @@ Note: \`azdo auth\` (no subcommand) preserves the legacy PAT-prompt entry point;
|
|
|
2540
2543
|
const globals = logoutCmd.optsWithGlobals();
|
|
2541
2544
|
await handleLogout(options, globals.org);
|
|
2542
2545
|
});
|
|
2543
|
-
const tokenCmd = command.command("token").description(
|
|
2546
|
+
const tokenCmd = command.command("token").description(
|
|
2547
|
+
"Print the credential the CLI uses for an org \u2014 a PAT or an OAuth access token \u2014 to stdout (for scripted API calls)"
|
|
2548
|
+
).option("--org <name>", "Azure DevOps organization (defaults: git remote -> config)");
|
|
2544
2549
|
tokenCmd.action(async () => {
|
|
2545
2550
|
const globals = tokenCmd.optsWithGlobals();
|
|
2546
2551
|
await handleToken(globals.org);
|
|
@@ -7209,6 +7214,11 @@ import os from "os";
|
|
|
7209
7214
|
var THROTTLE_MS = 10 * 60 * 1e3;
|
|
7210
7215
|
var FETCH_TIMEOUT_MS = 1500;
|
|
7211
7216
|
var REGISTRY_URL = "https://registry.npmjs.org/azdo-cli/latest";
|
|
7217
|
+
var UPDATE_CHECK_EXEMPT_COMMANDS = /* @__PURE__ */ new Set(["auth token"]);
|
|
7218
|
+
function skipsUpdateCheck(commandPath) {
|
|
7219
|
+
const withoutRoot = commandPath.slice(1);
|
|
7220
|
+
return UPDATE_CHECK_EXEMPT_COMMANDS.has(withoutRoot.join(" "));
|
|
7221
|
+
}
|
|
7212
7222
|
function getCachePath() {
|
|
7213
7223
|
return path2.join(os.homedir(), ".azdo", "update-check.json");
|
|
7214
7224
|
}
|
|
@@ -7344,7 +7354,17 @@ program.hook("preAction", () => {
|
|
|
7344
7354
|
initTraceWriter(trace);
|
|
7345
7355
|
}
|
|
7346
7356
|
});
|
|
7347
|
-
|
|
7357
|
+
function commandPathOf(command) {
|
|
7358
|
+
const names = [];
|
|
7359
|
+
for (let node = command; node !== null; node = node.parent) {
|
|
7360
|
+
names.unshift(node.name());
|
|
7361
|
+
}
|
|
7362
|
+
return names;
|
|
7363
|
+
}
|
|
7364
|
+
program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
7365
|
+
if (skipsUpdateCheck(commandPathOf(actionCommand))) {
|
|
7366
|
+
return;
|
|
7367
|
+
}
|
|
7348
7368
|
const notice = await getUpdateNotice({ enabled: program.opts().updateCheck });
|
|
7349
7369
|
if (notice) {
|
|
7350
7370
|
process.stderr.write(notice + "\n");
|