@elisra-devops/docgen-data-provider 1.134.0 → 1.136.0

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.
@@ -191,6 +191,12 @@ export default class TicketsDataProvider {
191
191
  GetQueryResultsByWiqlHref(wiqlHref: string, project: string): Promise<any>;
192
192
  GetQueryResultsByWiqlString(wiql: string, projectName: string): Promise<any>;
193
193
  GetQueryResultById(query: string, project: string): Promise<any>;
194
+ GetQueryDefinitionById(queryId: string, project: string): Promise<{
195
+ id: string;
196
+ name: string;
197
+ columns: any[];
198
+ wiql: any;
199
+ }>;
194
200
  private normalizeHistoricalAsOf;
195
201
  private normalizeHistoricalCompareValue;
196
202
  private normalizeTestPhaseValue;
@@ -371,8 +377,14 @@ export default class TicketsDataProvider {
371
377
  * source + first target work item). Trace queries are single-type per side in practice.
372
378
  */
373
379
  GetTraceColumnsByType(reqTestWiqlHref: string | undefined, testReqWiqlHref: string | undefined, project: string): Promise<{
374
- Requirement: any[];
375
- 'Test Case': any[];
380
+ 'req-test'?: {
381
+ Requirement: any[];
382
+ 'Test Case': any[];
383
+ };
384
+ 'test-req'?: {
385
+ Requirement: any[];
386
+ 'Test Case': any[];
387
+ };
376
388
  }>;
377
389
  }
378
390
  export {};
@@ -1302,6 +1302,17 @@ class TicketsDataProvider {
1302
1302
  var wiql = querie._links.wiql;
1303
1303
  return await this.GetQueryResultsByWiqlHref(wiql.href, project);
1304
1304
  }
1305
+ async GetQueryDefinitionById(queryId, project) {
1306
+ var _a, _b, _c, _d, _e;
1307
+ const url = `${this.orgUrl}${project}/_apis/wit/queries/${encodeURIComponent(queryId)}?$expand=all`;
1308
+ const def = await tfs_1.TFSServices.getItemContent(url, this.token);
1309
+ return {
1310
+ id: (_a = def === null || def === void 0 ? void 0 : def.id) !== null && _a !== void 0 ? _a : queryId,
1311
+ name: (_b = def === null || def === void 0 ? void 0 : def.name) !== null && _b !== void 0 ? _b : '',
1312
+ columns: (_c = def === null || def === void 0 ? void 0 : def.columns) !== null && _c !== void 0 ? _c : [],
1313
+ wiql: (_e = (_d = def === null || def === void 0 ? void 0 : def._links) === null || _d === void 0 ? void 0 : _d.wiql) !== null && _e !== void 0 ? _e : null,
1314
+ };
1315
+ }
1305
1316
  normalizeHistoricalAsOf(value) {
1306
1317
  const raw = String(value || '').trim();
1307
1318
  if (!raw) {
@@ -1663,29 +1674,40 @@ class TicketsDataProvider {
1663
1674
  skippedWorkItemIds,
1664
1675
  };
1665
1676
  }
1666
- collectHistoricalQueries(root, parentPath = '') {
1667
- const items = [];
1677
+ async collectHistoricalQueries(root, parentPath = '', acc = [], visited = new Set()) {
1668
1678
  if (!root) {
1669
- return items;
1679
+ return acc;
1670
1680
  }
1671
1681
  const name = String((root === null || root === void 0 ? void 0 : root.name) || '').trim();
1672
1682
  const currentPath = parentPath && name ? `${parentPath}/${name}` : name || parentPath;
1673
1683
  if (!(root === null || root === void 0 ? void 0 : root.isFolder)) {
1674
1684
  const id = String((root === null || root === void 0 ? void 0 : root.id) || '').trim();
1675
1685
  if (id) {
1676
- items.push({
1686
+ acc.push({
1677
1687
  id,
1678
1688
  queryName: name || id,
1679
1689
  path: parentPath || 'Shared Queries',
1680
1690
  });
1681
1691
  }
1682
- return items;
1692
+ return acc;
1683
1693
  }
1684
- const children = Array.isArray(root === null || root === void 0 ? void 0 : root.children) ? root.children : [];
1685
- for (const child of children) {
1686
- items.push(...this.collectHistoricalQueries(child, currentPath || 'Shared Queries'));
1694
+ const folderId = String((root === null || root === void 0 ? void 0 : root.id) || '').trim();
1695
+ if (folderId && visited.has(folderId)) {
1696
+ return acc;
1687
1697
  }
1688
- return items;
1698
+ if (folderId) {
1699
+ visited.add(folderId);
1700
+ }
1701
+ try {
1702
+ await this.ensureQueryChildren(root);
1703
+ }
1704
+ catch (err) {
1705
+ logger_1.default.warn(`collectHistoricalQueries: failed to expand folder "${name}" (id=${folderId}): ${err.message}`);
1706
+ return acc;
1707
+ }
1708
+ const children = Array.isArray(root === null || root === void 0 ? void 0 : root.children) ? root.children : [];
1709
+ await Promise.all(children.map((child) => this.collectHistoricalQueries(child, currentPath || 'Shared Queries', acc, visited)));
1710
+ return acc;
1689
1711
  }
1690
1712
  /**
1691
1713
  * Returns a flat list of shared queries for historical/as-of execution.
@@ -1699,7 +1721,7 @@ class TicketsDataProvider {
1699
1721
  return tfs_1.TFSServices.getItemContent(url, this.token);
1700
1722
  });
1701
1723
  const normalizedRoot = this.normalizeHistoricalQueryRoot(root);
1702
- const items = this.collectHistoricalQueries(normalizedRoot).filter((query) => query.id !== '');
1724
+ const items = (await this.collectHistoricalQueries(normalizedRoot)).filter((query) => query.id !== '');
1703
1725
  items.sort((a, b) => {
1704
1726
  const byPath = a.path.localeCompare(b.path);
1705
1727
  if (byPath !== 0)
@@ -2780,17 +2802,6 @@ class TicketsDataProvider {
2780
2802
  referenceName: c.referenceName,
2781
2803
  name: c.name,
2782
2804
  }));
2783
- const mergeCols = (a, b) => {
2784
- const seen = new Set();
2785
- const result = [];
2786
- for (const col of [...a, ...b]) {
2787
- if (!seen.has(col.referenceName)) {
2788
- seen.add(col.referenceName);
2789
- result.push(col);
2790
- }
2791
- }
2792
- return result;
2793
- };
2794
2805
  // Sample one work item to read its System.WorkItemType.
2795
2806
  // In OneHop query relations: !relation.source means root (target = source WI);
2796
2807
  // relation.source present means link (target = target WI).
@@ -2823,64 +2834,65 @@ class TicketsDataProvider {
2823
2834
  const fields = (_a = res === null || res === void 0 ? void 0 : res.value) !== null && _a !== void 0 ? _a : [];
2824
2835
  return new Set(fields.map((f) => f.referenceName));
2825
2836
  };
2826
- try {
2827
- // Step 1: fetch declared columns from provided query hrefs
2828
- let reqTestCols = [];
2829
- let testReqCols = [];
2830
- let reqTestRelations = [];
2831
- let testReqRelations = [];
2832
- if (reqTestWiqlHref) {
2833
- const qr = await tfs_1.TFSServices.getItemContent(reqTestWiqlHref, this.token);
2834
- reqTestCols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
2835
- reqTestRelations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
2836
- }
2837
- if (testReqWiqlHref) {
2838
- const qr = await tfs_1.TFSServices.getItemContent(testReqWiqlHref, this.token);
2839
- testReqCols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
2840
- testReqRelations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
2841
- }
2842
- const declaredCols = mergeCols(reqTestCols, testReqCols);
2843
- if (declaredCols.length === 0) {
2837
+ // Resolve per-side columns for one query independently.
2838
+ // srcIsReq: true = source WI is Requirement (req-test query), false = source WI is Test Case (test-req query).
2839
+ const resolveQuerySides = async (cols, relations, srcIsReq) => {
2840
+ if (cols.length === 0)
2844
2841
  return { Requirement: [], 'Test Case': [] };
2842
+ if (relations.length === 0) {
2843
+ // No items to sample — degrade to declared columns on both sides
2844
+ return { Requirement: cols, 'Test Case': cols };
2845
+ }
2846
+ const [srcType, tgtType] = await Promise.all([
2847
+ sampleWitType(relations, true),
2848
+ sampleWitType(relations, false),
2849
+ ]);
2850
+ const reqType = srcIsReq ? srcType : tgtType;
2851
+ const tcType = srcIsReq ? tgtType : srcType;
2852
+ if (!reqType || !tcType) {
2853
+ logger_1.default.warn('GetTraceColumnsByType: could not determine WIT type names — returning declared columns for both sides');
2854
+ return { Requirement: cols, 'Test Case': cols };
2845
2855
  }
2846
- // Step 2: sample WIT type names
2847
- // reqTest: source = Requirement, target = Test Case
2848
- // testReq: source = Test Case, target = Requirement
2849
- let reqTypeName;
2850
- let tcTypeName;
2851
- if (reqTestRelations.length > 0) {
2852
- [reqTypeName, tcTypeName] = await Promise.all([
2853
- sampleWitType(reqTestRelations, true),
2854
- sampleWitType(reqTestRelations, false),
2855
- ]);
2856
- }
2857
- if ((!reqTypeName || !tcTypeName) && testReqRelations.length > 0) {
2858
- const [tSrc, tTgt] = await Promise.all([
2859
- sampleWitType(testReqRelations, true),
2860
- sampleWitType(testReqRelations, false),
2861
- ]);
2862
- if (!tcTypeName)
2863
- tcTypeName = tSrc;
2864
- if (!reqTypeName)
2865
- reqTypeName = tTgt;
2866
- }
2867
- if (!reqTypeName || !tcTypeName) {
2868
- logger_1.default.warn('GetTraceColumnsByType: could not determine WIT type names — returning merged columns');
2869
- return { Requirement: declaredCols, 'Test Case': declaredCols };
2870
- }
2871
- // Step 3: fetch WIT field schemas and intersect with declared columns
2872
2856
  const [reqFieldSet, tcFieldSet] = await Promise.all([
2873
- fetchTypeFieldSet(reqTypeName),
2874
- fetchTypeFieldSet(tcTypeName),
2857
+ fetchTypeFieldSet(reqType),
2858
+ fetchTypeFieldSet(tcType),
2875
2859
  ]);
2876
2860
  return {
2877
- Requirement: declaredCols.filter((c) => reqFieldSet.has(c.referenceName)),
2878
- 'Test Case': declaredCols.filter((c) => tcFieldSet.has(c.referenceName)),
2861
+ Requirement: cols.filter((c) => reqFieldSet.has(c.referenceName)),
2862
+ 'Test Case': cols.filter((c) => tcFieldSet.has(c.referenceName)),
2879
2863
  };
2864
+ };
2865
+ try {
2866
+ const result = {};
2867
+ if (reqTestWiqlHref) {
2868
+ try {
2869
+ const qr = await tfs_1.TFSServices.getItemContent(reqTestWiqlHref, this.token);
2870
+ const cols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
2871
+ const relations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
2872
+ result['req-test'] = await resolveQuerySides(cols, relations, true);
2873
+ }
2874
+ catch (err) {
2875
+ logger_1.default.error(`GetTraceColumnsByType[req-test] failed: ${err.message}`);
2876
+ result['req-test'] = { Requirement: [], 'Test Case': [] };
2877
+ }
2878
+ }
2879
+ if (testReqWiqlHref) {
2880
+ try {
2881
+ const qr = await tfs_1.TFSServices.getItemContent(testReqWiqlHref, this.token);
2882
+ const cols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
2883
+ const relations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
2884
+ result['test-req'] = await resolveQuerySides(cols, relations, false);
2885
+ }
2886
+ catch (err) {
2887
+ logger_1.default.error(`GetTraceColumnsByType[test-req] failed: ${err.message}`);
2888
+ result['test-req'] = { Requirement: [], 'Test Case': [] };
2889
+ }
2890
+ }
2891
+ return result;
2880
2892
  }
2881
2893
  catch (err) {
2882
2894
  logger_1.default.error(`GetTraceColumnsByType failed: ${err.message}`);
2883
- return { Requirement: [], 'Test Case': [] };
2895
+ return {};
2884
2896
  }
2885
2897
  }
2886
2898
  }