azdo-cli 0.22.0-develop.868 → 0.22.0-develop.874
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 +1 -0
- package/dist/index.js +55 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,7 @@ azdo config set credentialStore dpapi --copy-credentials
|
|
|
45
45
|
|
|
46
46
|
# Read a work item
|
|
47
47
|
azdo get-item 12345
|
|
48
|
+
azdo get-item 12345 --json # machine-readable: identities, tags and all relations incl. pull requests
|
|
48
49
|
|
|
49
50
|
# Download images embedded in a work item's rich-text fields (opt-in)
|
|
50
51
|
azdo get-item 12345 --download-images # saved to the system temp dir
|
package/dist/index.js
CHANGED
|
@@ -475,6 +475,9 @@ var DEFAULT_FIELDS = [
|
|
|
475
475
|
"System.State",
|
|
476
476
|
"System.WorkItemType",
|
|
477
477
|
"System.AssignedTo",
|
|
478
|
+
"System.CreatedBy",
|
|
479
|
+
"System.CreatedDate",
|
|
480
|
+
"System.Tags",
|
|
478
481
|
"System.Description",
|
|
479
482
|
"Microsoft.VSTS.Common.AcceptanceCriteria",
|
|
480
483
|
"Microsoft.VSTS.TCM.ReproSteps",
|
|
@@ -809,6 +812,30 @@ async function getOrgFieldNames(context, cred) {
|
|
|
809
812
|
const data = await response.json();
|
|
810
813
|
return (data.value ?? []).map((f) => f.referenceName);
|
|
811
814
|
}
|
|
815
|
+
function toIdentity(ref) {
|
|
816
|
+
if (!ref) return null;
|
|
817
|
+
return {
|
|
818
|
+
displayName: ref.displayName ?? null,
|
|
819
|
+
uniqueName: ref.uniqueName ?? null,
|
|
820
|
+
id: ref.id ?? null
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
var PULL_REQUEST_ARTIFACT = /^vstfs:\/\/\/Git\/PullRequestId\/(.+)$/i;
|
|
824
|
+
function mapRelations(relations) {
|
|
825
|
+
return (relations ?? []).map((r) => {
|
|
826
|
+
const entry = { rel: r.rel, name: r.attributes?.name ?? null, url: r.url };
|
|
827
|
+
const workItemMatch = /\/workItems\/(\d+)$/i.exec(r.url);
|
|
828
|
+
if (workItemMatch) entry.workItemId = Number(workItemMatch[1]);
|
|
829
|
+
const prMatch = PULL_REQUEST_ARTIFACT.exec(r.url);
|
|
830
|
+
if (prMatch) {
|
|
831
|
+
const [projectId, repositoryId, prId] = prMatch[1].split(/%2F|\//i);
|
|
832
|
+
if (projectId && repositoryId && /^\d+$/.test(prId ?? "")) {
|
|
833
|
+
entry.pullRequest = { id: Number(prId), repositoryId, projectId };
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return entry;
|
|
837
|
+
});
|
|
838
|
+
}
|
|
812
839
|
function buildCombinedDescription(fields) {
|
|
813
840
|
const parts = [];
|
|
814
841
|
if (fields["System.Description"]) {
|
|
@@ -864,6 +891,11 @@ async function getWorkItem(context, id, cred, extraFields) {
|
|
|
864
891
|
state: data.fields["System.State"],
|
|
865
892
|
type: data.fields["System.WorkItemType"],
|
|
866
893
|
assignedTo: data.fields["System.AssignedTo"]?.displayName ?? null,
|
|
894
|
+
assignedToIdentity: toIdentity(data.fields["System.AssignedTo"]),
|
|
895
|
+
createdBy: toIdentity(data.fields["System.CreatedBy"]),
|
|
896
|
+
createdDate: data.fields["System.CreatedDate"] ?? null,
|
|
897
|
+
tags: parseTags(data.fields["System.Tags"]),
|
|
898
|
+
relations: mapRelations(relationsData.relations),
|
|
867
899
|
description: buildCombinedDescription(data.fields),
|
|
868
900
|
areaPath: data.fields["System.AreaPath"],
|
|
869
901
|
iterationPath: data.fields["System.IterationPath"],
|
|
@@ -2007,6 +2039,20 @@ function convertRichText(html, markdown) {
|
|
|
2007
2039
|
if (!html) return "";
|
|
2008
2040
|
return markdown ? toMarkdown(html) : stripHtml(html);
|
|
2009
2041
|
}
|
|
2042
|
+
function toJsonDocument(workItem) {
|
|
2043
|
+
return {
|
|
2044
|
+
id: workItem.id,
|
|
2045
|
+
title: workItem.title,
|
|
2046
|
+
description: workItem.description ? toMarkdown(workItem.description) : "",
|
|
2047
|
+
state: workItem.state,
|
|
2048
|
+
tags: workItem.tags ?? [],
|
|
2049
|
+
assignedTo: workItem.assignedToIdentity ?? null,
|
|
2050
|
+
createdBy: workItem.createdBy ?? null,
|
|
2051
|
+
createdDate: workItem.createdDate ?? null,
|
|
2052
|
+
url: workItem.url,
|
|
2053
|
+
relations: workItem.relations ?? []
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2010
2056
|
function formatMarkdownField(fieldLabel, value) {
|
|
2011
2057
|
if (value.includes("\n")) {
|
|
2012
2058
|
return `${fieldLabel}:
|
|
@@ -2084,13 +2130,17 @@ function formatWorkItem(workItem, short, markdown = false) {
|
|
|
2084
2130
|
}
|
|
2085
2131
|
function createGetItemCommand() {
|
|
2086
2132
|
const command = new Command("get-item");
|
|
2087
|
-
command.description("Retrieve an Azure DevOps work item by ID").argument("<id>", "work item ID").option("--org <org>", "Azure DevOps organization").option("--project <project>", "Azure DevOps project").option("--short", "show abbreviated output").option("--fields <fields>", "comma-separated additional field reference names").option("--markdown", "convert rich text fields to markdown");
|
|
2133
|
+
command.description("Retrieve an Azure DevOps work item by ID").argument("<id>", "work item ID").option("--org <org>", "Azure DevOps organization").option("--project <project>", "Azure DevOps project").option("--short", "show abbreviated output").option("--fields <fields>", "comma-separated additional field reference names").option("--markdown", "convert rich text fields to markdown").option("--json", "output { id, title, description (markdown), state, tags, assignedTo, createdBy, createdDate, url, relations } (assignedTo/createdBy: { displayName, uniqueName, id }; relations include pull requests)");
|
|
2088
2134
|
addImageDownloadOptions(command);
|
|
2089
2135
|
command.action(
|
|
2090
2136
|
async (idStr, options) => {
|
|
2091
2137
|
const id = parseWorkItemId(idStr);
|
|
2092
2138
|
validateOrgProjectPair(options);
|
|
2093
2139
|
const imageOptions = resolveImageDownloadOptionsOrExit(options);
|
|
2140
|
+
if (options.json && (imageOptions.enabled || options.downloadImages || options.resizeImages !== void 0 || options.imagesPath !== void 0)) {
|
|
2141
|
+
process.stderr.write("Error: --json cannot be combined with image download options.\n");
|
|
2142
|
+
process.exit(1);
|
|
2143
|
+
}
|
|
2094
2144
|
let context;
|
|
2095
2145
|
try {
|
|
2096
2146
|
context = resolveContext(options);
|
|
@@ -2098,6 +2148,10 @@ function createGetItemCommand() {
|
|
|
2098
2148
|
const scopedCfg = resolveScopedConfig(context.org);
|
|
2099
2149
|
const fieldsList = options.fields === void 0 ? parseRequestedFields(scopedCfg.fields) : parseRequestedFields(options.fields);
|
|
2100
2150
|
const workItem = await getWorkItem(context, id, credential, fieldsList);
|
|
2151
|
+
if (options.json) {
|
|
2152
|
+
process.stdout.write(JSON.stringify(toJsonDocument(workItem)) + "\n");
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2101
2155
|
const markdownEnabled = options.markdown ?? scopedCfg.markdown ?? false;
|
|
2102
2156
|
const output = formatWorkItem(workItem, options.short ?? false, markdownEnabled);
|
|
2103
2157
|
process.stdout.write(output + "\n");
|