@letpeoplework/lighthouse-client 1.10.0 → 1.12.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.
package/dist/index.js CHANGED
@@ -36,6 +36,20 @@ const PROCESS_BEHAVIOR_CHART_ROUTES = {
36
36
  const isProcessBehaviorMetricType = (value) => Object.hasOwn(PROCESS_BEHAVIOR_CHART_ROUTES, value);
37
37
  //#endregion
38
38
  //#region src/usageData.ts
39
+ const reportTemplateWeDisclose = { "then-and-now": "ThenAndNow" };
40
+ /**
41
+ * The opening of a report Lighthouse sent: its type and nothing else about it. A refused read, or a report of a
42
+ * type this version does not know, counts nothing.
43
+ */
44
+ const reportOpenedOccurrencesOf = (answered) => {
45
+ if (!answered.ok || !isRecord$1(answered.value)) return [];
46
+ const { templateKey } = answered.value;
47
+ const reportTemplate = Object.entries(reportTemplateWeDisclose).find(([key]) => key === templateKey)?.[1];
48
+ return reportTemplate === void 0 ? [] : [{
49
+ name: "ReportOpened",
50
+ reportTemplate
51
+ }];
52
+ };
39
53
  /**
40
54
  * When a vote was cast, from Lighthouse's answer rather than this machine's clock: Lighthouse counts days in
41
55
  * the instance's time zone and knows which cadence days are blacked out. The web counts it the same way.
@@ -241,13 +255,26 @@ const textOf = (value) => typeof value === "string" && value.length > 0 ? value
241
255
  const isDay = (value) => isText(value) && formatCalendarDay(value) !== null;
242
256
  /** The calendar day as a person reads it, or the text exactly as sent when it is not one. */
243
257
  const dayOf = (wire) => formatCalendarDay(wire) ?? wire;
244
- /** The date a list of chances gives for one probability, or undefined when it holds none for it. */
245
- const expectedDateAt = (chances, probability) => {
258
+ /** The chance a list gives for one probability, or undefined when it holds none for it. */
259
+ const chanceAt = (chances, probability) => {
246
260
  if (!Array.isArray(chances)) return;
247
261
  const chance = chances.find((entry) => isRecord(entry) && entry.probability === probability);
248
- return isRecord(chance) ? textOf(chance.expectedDate) : void 0;
262
+ return isRecord(chance) ? chance : void 0;
249
263
  };
250
264
  //#endregion
265
+ //#region src/forecastPercentileText.ts
266
+ /**
267
+ * The years of the horizon a percentile lies beyond, or undefined when its date is the forecast. Keyed on
268
+ * the flag itself, never on the server's version: an older Lighthouse never sends it.
269
+ */
270
+ const yearsBeyondHorizon = (percentile) => isRecord(percentile) && percentile.beyondHorizon === true && isNumber(percentile.horizonYears) ? percentile.horizonYears : void 0;
271
+ /** The words shown in place of a date for a percentile too few simulated runs reached. */
272
+ const moreThanYearsText = (horizonYears) => `More than ${horizonYears} years`;
273
+ /** A percentile's day as a person reads it, or "More than 5 years" when it lies beyond that horizon. */
274
+ const describePercentileDay = (expectedDate, horizonYearsBeyond) => horizonYearsBeyond === void 0 ? dayOf(expectedDate) : moreThanYearsText(horizonYearsBeyond);
275
+ /** One percentile as text: its day, or the words when it lies beyond the horizon. */
276
+ const describePercentileDate = (percentile) => describePercentileDay(percentile.expectedDate, yearsBeyondHorizon(percentile));
277
+ //#endregion
251
278
  //#region src/ownerWording.ts
252
279
  /** A mark for a cell Lighthouse sent nothing for. */
253
280
  const NOT_SENT = "—";
@@ -407,9 +434,11 @@ const startOf = (value) => {
407
434
  observedOn: void 0,
408
435
  likelyBy: void 0
409
436
  };
437
+ const chance = chanceAt(value.percentiles, LISTED_CHANCE$1);
410
438
  return {
411
439
  observedOn: value.source === "Observed" ? textOf(value.observedDate) : void 0,
412
- likelyBy: expectedDateAt(value.percentiles, LISTED_CHANCE$1)
440
+ likelyBy: textOf(chance?.expectedDate),
441
+ likelyByBeyondHorizonYears: yearsBeyondHorizon(chance)
413
442
  };
414
443
  };
415
444
  const readFeatureListItem = (value) => {
@@ -419,6 +448,7 @@ const readFeatureListItem = (value) => {
419
448
  const state = textOf(value.state);
420
449
  const totalWork = workOf(value.totalWork);
421
450
  const remainingWork = workOf(value.remainingWork);
451
+ const completion = chanceAt(value.forecasts, LISTED_CHANCE$1);
422
452
  if (referenceId === void 0 || name === void 0 || state === void 0 || totalWork === null || remainingWork === null) return null;
423
453
  return {
424
454
  referenceId,
@@ -428,7 +458,8 @@ const readFeatureListItem = (value) => {
428
458
  remainingWork,
429
459
  cannotBeForecast: Array.isArray(value.teamsWithoutForecast) && value.teamsWithoutForecast.length > 0,
430
460
  start: startOf(value.startForecast),
431
- likelyBy: expectedDateAt(value.forecasts, LISTED_CHANCE$1)
461
+ likelyBy: textOf(completion?.expectedDate),
462
+ likelyByBeyondHorizonYears: yearsBeyondHorizon(completion)
432
463
  };
433
464
  };
434
465
  /**
@@ -464,12 +495,15 @@ const describeFeatureProgress = (feature, terms) => `${feature.totalWork - featu
464
495
  const describeFeatureStart = (feature) => {
465
496
  if (feature.start.observedOn !== void 0) return dayOf(feature.start.observedOn);
466
497
  if (feature.cannotBeForecast) return CANNOT_FORECAST_SHORT;
467
- return feature.start.likelyBy === void 0 ? "—" : dayOf(feature.start.likelyBy);
498
+ return feature.start.likelyBy === void 0 ? "—" : describePercentileDay(feature.start.likelyBy, feature.start.likelyByBeyondHorizonYears);
468
499
  };
469
- /** The day the Feature is 85% likely to be done by, "Cannot forecast", or the mark when none was sent. */
500
+ /**
501
+ * The day the Feature is 85% likely to be done by, "More than 5 years" when that lies beyond the simulation
502
+ * horizon, "Cannot forecast", or the mark when none was sent.
503
+ */
470
504
  const describeFeatureCompletion = (feature) => {
471
505
  if (feature.cannotBeForecast) return CANNOT_FORECAST_SHORT;
472
- return feature.likelyBy === void 0 ? "—" : dayOf(feature.likelyBy);
506
+ return feature.likelyBy === void 0 ? "—" : describePercentileDay(feature.likelyBy, feature.likelyByBeyondHorizonYears);
473
507
  };
474
508
  /** One Feature as a row of the list, in the order of its headings. */
475
509
  const describeFeatureRow = (feature, terms) => [
@@ -632,6 +666,7 @@ const readDeliveryListItem = (value) => {
632
666
  const name = textOf(value.name);
633
667
  const date = textOf(value.date);
634
668
  if (name === void 0 || date === void 0) return null;
669
+ const likely = chanceAt(value.completionDates, LISTED_CHANCE);
635
670
  return {
636
671
  id: value.id,
637
672
  name,
@@ -643,7 +678,8 @@ const readDeliveryListItem = (value) => {
643
678
  cannotBeForecast: teamsWithoutForecastIn(value),
644
679
  hasSufficientData: flagOf(value.hasSufficientData),
645
680
  isOverdue: flagOf(value.isOverdue),
646
- likelyBy: expectedDateAt(value.completionDates, LISTED_CHANCE)
681
+ likelyBy: textOf(likely?.expectedDate),
682
+ likelyByBeyondHorizonYears: yearsBeyondHorizon(likely)
647
683
  };
648
684
  };
649
685
  /**
@@ -727,7 +763,7 @@ const describeDeliveryRow = (delivery, terms) => [
727
763
  delivery.featureCount === void 0 ? "—" : String(delivery.featureCount),
728
764
  describeDeliveryDone(delivery, terms),
729
765
  describeDeliveryLikelihood(delivery),
730
- delivery.likelyBy === void 0 ? "—" : dayOf(delivery.likelyBy)
766
+ delivery.likelyBy === void 0 ? "—" : describePercentileDay(delivery.likelyBy, delivery.likelyByBeyondHorizonYears)
731
767
  ];
732
768
  /** What heads the archived Deliveries, below the active ones: "Archived Deliveries". */
733
769
  const describeArchivedDeliveriesTitle = (terms) => `Archived ${terms.deliveries}`;
@@ -830,18 +866,23 @@ const describeDeliveryFeatureRow = (feature) => [
830
866
  ];
831
867
  /** The forecast distribution's column headings. */
832
868
  const describeDeliveryChanceHeadings = () => ["Chance", "Done by"];
833
- /** One chance of the day's forecast: "85%" and the day it is that likely to be done by. */
834
- const describeDeliveryChanceRow = (chance) => [`${chance.probability}%`, dayOf(chance.expectedDate)];
869
+ /** One chance of the day's forecast: "85%" and the day it is that likely to be done by, or "More than 5 years". */
870
+ const describeDeliveryChanceRow = (chance) => [`${chance.probability}%`, describePercentileDate(chance)];
835
871
  //#endregion
836
872
  //#region src/forecastWording.ts
837
- const optionalBoolean = (value) => {
873
+ const optionalBoolean$1 = (value) => {
838
874
  if (value === void 0 || typeof value === "boolean") return value;
839
875
  return null;
840
876
  };
841
- const readChanceByDay = (value) => isRecord(value) && isNumber(value.probability) && isDay(value.expectedDate) ? {
842
- probability: value.probability,
843
- expectedDate: value.expectedDate
844
- } : null;
877
+ const readChanceByDay = (value) => {
878
+ if (!isRecord(value) || !isNumber(value.probability) || !isDay(value.expectedDate)) return null;
879
+ return {
880
+ probability: value.probability,
881
+ expectedDate: value.expectedDate,
882
+ ...typeof value.beyondHorizon === "boolean" ? { beyondHorizon: value.beyondHorizon } : {},
883
+ ...isNumber(value.horizonYears) ? { horizonYears: value.horizonYears } : {}
884
+ };
885
+ };
845
886
  const readChanceOfCount = (value) => isRecord(value) && isNumber(value.probability) && isNumber(value.value) ? {
846
887
  probability: value.probability,
847
888
  value: value.value
@@ -857,8 +898,8 @@ const readManualForecast = (value) => {
857
898
  const { remainingItems, targetDate, likelihood } = value;
858
899
  const whenForecasts = readEvery$1(value.whenForecasts, readChanceByDay);
859
900
  const howManyForecasts = readEvery$1(value.howManyForecasts, readChanceOfCount);
860
- const filterApplied = optionalBoolean(value.filterApplied);
861
- const hasSufficientData = optionalBoolean(value.hasSufficientData);
901
+ const filterApplied = optionalBoolean$1(value.filterApplied);
902
+ const hasSufficientData = optionalBoolean$1(value.hasSufficientData);
862
903
  if (!isNumber(remainingItems) || !(targetDate === null || isDay(targetDate)) || !(likelihood === null || isNumber(likelihood)) || whenForecasts === null || howManyForecasts === null || filterApplied === null || hasSufficientData === null) return null;
863
904
  return {
864
905
  remainingItems,
@@ -1145,13 +1186,28 @@ const readRunChart = (value, range) => {
1145
1186
  const optionalText = (value) => isText(value) ? value : void 0;
1146
1187
  const optionalNumber = (value) => isNumber(value) ? value : void 0;
1147
1188
  const optionalDay = (value) => isDay(value) ? value : void 0;
1189
+ const optionalBoolean = (value) => typeof value === "boolean" ? value : void 0;
1190
+ const STALE_REASON_KINDS = [
1191
+ "TimeInState",
1192
+ "BlockedDuration",
1193
+ "TimeInStateWhileBlocked"
1194
+ ];
1195
+ const isStaleReasonKind = (value) => STALE_REASON_KINDS.some((kind) => kind === value);
1196
+ const readStaleReason = (value) => isRecord(value) && isStaleReasonKind(value.kind) && isNumber(value.days) ? {
1197
+ kind: value.kind,
1198
+ days: value.days,
1199
+ stateName: optionalText(value.stateName)
1200
+ } : null;
1201
+ const optionalStaleReasons = (value) => Array.isArray(value) ? value.map(readStaleReason).filter((reason) => reason !== null) : void 0;
1148
1202
  const readInProgressItem = (value) => isRecord(value) && (value.isBlocked === void 0 || typeof value.isBlocked === "boolean") ? {
1149
1203
  isBlocked: value.isBlocked,
1150
1204
  referenceId: optionalText(value.referenceId),
1151
1205
  name: optionalText(value.name),
1152
1206
  state: optionalText(value.state),
1153
1207
  workItemAge: optionalNumber(value.workItemAge),
1154
- blockedSince: optionalDay(value.blockedSince)
1208
+ blockedSince: optionalDay(value.blockedSince),
1209
+ isStale: optionalBoolean(value.isStale),
1210
+ staleReasons: optionalStaleReasons(value.staleReasons)
1155
1211
  } : null;
1156
1212
  const readInProgressNow = (value) => {
1157
1213
  if (!isRecord(value) || !isDay(value.asOfDate) || !isNumber(value.count)) return null;
@@ -1350,6 +1406,7 @@ const metricsHeadlineLabel = (part, scope, terms) => {
1350
1406
  throughput: `Total ${terms.throughput}`,
1351
1407
  arrivals: "Total Arrivals",
1352
1408
  blocked: `${terms.blocked} ${counted.many}`,
1409
+ stale: `Stale ${counted.many}`,
1353
1410
  totalWorkItemAge: `Total ${terms.workItemAge}`,
1354
1411
  predictabilityScore: "Predictability Score",
1355
1412
  cycleTimePercentiles: `${terms.cycleTime} percentiles`,
@@ -1393,27 +1450,31 @@ const describeInProgressNow = (now, scope, terms, systemWipLimit) => ({
1393
1450
  value: String(now.count),
1394
1451
  detail: systemWipLimit === void 0 ? "" : wipLimitOf(systemWipLimit, scope, terms)
1395
1452
  });
1453
+ const blockedFlag = (item) => item.isBlocked;
1454
+ const staleFlag = (item) => item.isStale;
1455
+ const saysWhichAre = (now, flag) => now.items.some((item) => flag(item) !== void 0);
1456
+ const countFlaggedNow = (part, flag, now, scope, terms) => saysWhichAre(now, flag) ? {
1457
+ label: metricsHeadlineLabel(part, scope, terms),
1458
+ value: String(now.items.filter((item) => flag(item) === true).length),
1459
+ detail: ""
1460
+ } : null;
1396
1461
  /** "Blocked Work Items 2", or null when Lighthouse does not say which items are blocked. */
1397
- const describeBlockedNow = (now, scope, terms) => {
1398
- if (!now.items.some((item) => item.isBlocked !== void 0)) return null;
1399
- const blocked = now.items.filter((item) => item.isBlocked === true).length;
1400
- return {
1401
- label: metricsHeadlineLabel("blocked", scope, terms),
1402
- value: String(blocked),
1403
- detail: ""
1404
- };
1405
- };
1462
+ const describeBlockedNow = (now, scope, terms) => countFlaggedNow("blocked", blockedFlag, now, scope, terms);
1463
+ /** "Stale Work Items 2", or null when Lighthouse does not say which items are stale. */
1464
+ const describeStaleNow = (now, scope, terms) => countFlaggedNow("stale", staleFlag, now, scope, terms);
1406
1465
  /**
1407
1466
  * The sentences that stand in for what a WIP answer cannot show: no System WIP Limit, a Lighthouse that does
1408
- * not say which Work Items are Blocked (which is not the same as none being Blocked), and nothing in progress.
1409
- * A limit of null means the Team or Portfolio could not be read; it may well have one, so nothing is said.
1467
+ * not say which Work Items are Blocked or Stale (which is not the same as none being so), and nothing in
1468
+ * progress. A limit of null means the Team or Portfolio could not be read; it may well have one, so nothing
1469
+ * is said.
1410
1470
  */
1411
1471
  const describeWhatWipLeavesUnsaid = (now, scope, terms, systemWipLimit) => {
1412
1472
  const counted = countedOf(scope, terms);
1413
- const blockedUnknown = now.items.length > 0 && now.items.every((item) => item.isBlocked === void 0);
1473
+ const silentOn = (flag) => now.items.length > 0 && !saysWhichAre(now, flag);
1414
1474
  return [
1415
1475
  ...systemWipLimit === void 0 ? [`No System ${terms.wip} Limit is set.`] : [],
1416
- ...blockedUnknown ? [`Lighthouse does not say which ${counted.many} are ${terms.blocked}.`] : [],
1476
+ ...silentOn(blockedFlag) ? [`Lighthouse does not say which ${counted.many} are ${terms.blocked}.`] : [],
1477
+ ...silentOn(staleFlag) ? [`Lighthouse does not say which ${counted.many} are Stale.`] : [],
1417
1478
  ...now.items.length === 0 ? [`No ${counted.many} are in progress.`] : []
1418
1479
  ];
1419
1480
  };
@@ -2117,6 +2178,114 @@ const readNameOfMyVote = async (client, teamId, workItem, voterKey) => {
2117
2178
  return log.ok ? nameOfMyVote(log.value) : null;
2118
2179
  };
2119
2180
  //#endregion
2181
+ //#region src/reportWording.ts
2182
+ const readWindow = (value) => isRecord(value) && isDay(value.start) && isDay(value.end) ? {
2183
+ start: value.start,
2184
+ end: value.end
2185
+ } : null;
2186
+ /** The report's name and windows, or null when the answer does not carry all three. */
2187
+ const readReport = (value) => {
2188
+ if (!isRecord(value) || !isRecord(value.thenAndNow)) return null;
2189
+ const name = textOf(value.name);
2190
+ const thenWindow = readWindow(value.thenAndNow.thenWindow);
2191
+ const nowWindow = readWindow(value.thenAndNow.nowWindow);
2192
+ if (name === void 0 || thenWindow === null || nowWindow === null) return null;
2193
+ return {
2194
+ name,
2195
+ thenWindow,
2196
+ nowWindow
2197
+ };
2198
+ };
2199
+ const readReportListItem = (value) => {
2200
+ if (!isRecord(value) || typeof value.id !== "number") return null;
2201
+ const name = textOf(value.name);
2202
+ if (name === void 0) return null;
2203
+ return {
2204
+ id: value.id,
2205
+ name,
2206
+ templateKey: textOf(value.templateKey),
2207
+ createdOn: textOf(value.createdOn)
2208
+ };
2209
+ };
2210
+ /**
2211
+ * Every report in the list, or null when the answer holds no list or any one report comes without its id or
2212
+ * name: a row that cannot say which report it is would misname the whole list.
2213
+ */
2214
+ const readReportList = (value) => {
2215
+ if (!isRecord(value) || !Array.isArray(value.reports)) return null;
2216
+ const items = value.reports.map(readReportListItem);
2217
+ return items.every((item) => item !== null) ? items : null;
2218
+ };
2219
+ const ownerTerm$1 = (kind, terms) => kind === "team" ? terms.team : terms.portfolio;
2220
+ /** The owner as the instance names it, "Team Lightspeed", or by its id when its name could not be read. */
2221
+ const describeReportOwner = (kind, id, owner, terms) => {
2222
+ const term = ownerTerm$1(kind, terms);
2223
+ const name = isRecord(owner) ? textOf(owner.name) : void 0;
2224
+ return name === void 0 ? `${term} [id: ${id}]` : `${term} ${name}`;
2225
+ };
2226
+ const describeWindow = (label, window) => `${label} ${dayOf(window.start)} – ${dayOf(window.end)}`;
2227
+ /** The report's name, its owner and its two windows, one to a line. */
2228
+ const describeReportSummary = (report, owner) => [
2229
+ report.name,
2230
+ owner,
2231
+ `${describeWindow("Then", report.thenWindow)} · ${describeWindow("Now", report.nowWindow)}`
2232
+ ].join("\n");
2233
+ const describeReportCount = (count) => {
2234
+ if (count === 0) return "No reports";
2235
+ return count === 1 ? "1 report" : `${count} reports`;
2236
+ };
2237
+ const describeReportListItem = (item) => [
2238
+ `${item.name} [id: ${item.id}]`,
2239
+ item.templateKey,
2240
+ item.createdOn === void 0 ? void 0 : `created ${dayOf(item.createdOn)}`
2241
+ ].filter((part) => part !== void 0).join(" · ");
2242
+ /** How many reports the owner has, then each report's name, type and created day. */
2243
+ const describeReportListSummary = (reports, owner) => [`${owner} · ${describeReportCount(reports.length)}`, ...reports.map(describeReportListItem)].join("\n");
2244
+ const summariseReport = (value, owner) => {
2245
+ const report = readReport(value);
2246
+ return report === null ? null : describeReportSummary(report, owner);
2247
+ };
2248
+ const summariseReportList = (value, owner) => {
2249
+ const reports = readReportList(value);
2250
+ return reports === null ? null : describeReportListSummary(reports, owner);
2251
+ };
2252
+ const FORBIDDEN = 403;
2253
+ const NOT_FOUND = 404;
2254
+ const NOTHING_THERE = {
2255
+ list: (owner) => `There is no such ${owner}.`,
2256
+ report: (owner) => `There is no such report for that ${owner}.`
2257
+ };
2258
+ /**
2259
+ * Why a report or a list could not be read, in words the reader can act on: the web's sentence where it has
2260
+ * one. Any other refusal, the client's own "upgrade Lighthouse" among them, keeps its category and reason.
2261
+ */
2262
+ const describeReportRefusal = (error, kind, read, terms) => {
2263
+ if (error.statusCode === FORBIDDEN) return `You have no access to that ${ownerTerm$1(kind, terms)}'s reports.`;
2264
+ if (error.problemCode === "template-not-supported") return "This report was made by a newer version of Lighthouse and can't be shown here.";
2265
+ if (error.statusCode === NOT_FOUND) return NOTHING_THERE[read](ownerTerm$1(kind, terms));
2266
+ return `${error.category}: ${error.reason}`;
2267
+ };
2268
+ /**
2269
+ * {@link describeReportRefusal} in the instance's own words. A refusal the client made before asking, as for a
2270
+ * Lighthouse too old for reports, asks that Lighthouse nothing more, not even its words.
2271
+ */
2272
+ const readReportRefusal = async (source, error, kind, read) => describeReportRefusal(error, kind, read, error.statusCode === void 0 ? SEEDED_TERMS : await readTerms(source));
2273
+ //#endregion
2274
+ //#region src/reportReads.ts
2275
+ /** The owner's list of reports, exactly as Lighthouse answers it. */
2276
+ const readOwnersReports = (reads, owner) => owner.kind === "team" ? reads.getTeamReports(owner.id) : reads.getPortfolioReports(owner.id);
2277
+ /** One of the owner's reports, exactly as Lighthouse answers it. */
2278
+ const readOwnersReport = (reads, owner, reportId) => owner.kind === "team" ? reads.getTeamReport(owner.id, reportId) : reads.getPortfolioReport(owner.id, reportId);
2279
+ /**
2280
+ * {@link describeReportOwner} for an owner read from Lighthouse. Its name only labels a summary, so an owner that
2281
+ * cannot be read is named by its id instead, and this never fails.
2282
+ */
2283
+ const readReportOwner = async (source, owner) => {
2284
+ const read = owner.kind === "team" ? source.getTeam(owner.id) : source.getPortfolio(owner.id);
2285
+ const [terms, named] = await Promise.all([readTerms(source), read.then((answer) => answer.ok ? answer.value : void 0, () => void 0)]);
2286
+ return describeReportOwner(owner.kind, owner.id, named, terms);
2287
+ };
2288
+ //#endregion
2120
2289
  //#region src/usageDataReporter.ts
2121
2290
  /** A command's own answer never waits on usage data for longer than this, whatever Lighthouse does. */
2122
2291
  const USAGE_DATA_BUDGET_MS = 1e3;
@@ -3158,7 +3327,9 @@ const FEATURE_REQUIRES_SERVER_NEWER_THAN = {
3158
3327
  deliveryMetricsHistory: "v26.5.29.5",
3159
3328
  sleRisk: "v26.9.19.10",
3160
3329
  teamRefinement: "v26.10.3.6",
3161
- refinementVotes: "v26.10.3.6"
3330
+ refinementVotes: "v26.10.3.6",
3331
+ staleness: "v26.10.16.6",
3332
+ reports: "v26.10.10.1"
3162
3333
  };
3163
3334
  /**
3164
3335
  * Parses a Lighthouse version string ("v26.5.24.10", "26.5.24") into numeric
@@ -3220,6 +3391,7 @@ const createLighthouseClient = (configuration, dependencies = {}) => {
3220
3391
  }
3221
3392
  };
3222
3393
  };
3394
+ const readReports = async (route) => await ensureServerSupports("reports") ?? requestJson(configuration, dependencies, route, { method: "GET" });
3223
3395
  return {
3224
3396
  checkConnectivity: async () => {
3225
3397
  const fetchDependency = getFetchDependency(dependencies);
@@ -3296,6 +3468,10 @@ const createLighthouseClient = (configuration, dependencies = {}) => {
3296
3468
  headers: voterKeyHeaders(options?.voterKey)
3297
3469
  });
3298
3470
  },
3471
+ getTeamReports: async (teamId) => readReports(`/v1/teams/${teamId}/reports`),
3472
+ getTeamReport: async (teamId, reportId) => readReports(`/v1/teams/${teamId}/reports/${reportId}`),
3473
+ getPortfolioReports: async (portfolioId) => readReports(`/v1/portfolios/${portfolioId}/reports`),
3474
+ getPortfolioReport: async (portfolioId, reportId) => readReports(`/v1/portfolios/${portfolioId}/reports/${reportId}`),
3299
3475
  getTerminology: async () => requestJson(configuration, dependencies, "/v1/terminology/all", { method: "GET" }),
3300
3476
  listPortfolios: async () => requestJson(configuration, dependencies, "/v1/portfolios", { method: "GET" }),
3301
3477
  getPortfolio: async (portfolioId) => requestJson(configuration, dependencies, `/v1/portfolios/${portfolioId}`, { method: "GET" }),
@@ -3615,4 +3791,4 @@ const usageDataCalls = (configuration, dependencies) => {
3615
3791
  };
3616
3792
  };
3617
3793
  //#endregion
3618
- export { BLACKOUT_RULE_LIST_HEADINGS, BLACKOUT_RULE_LIST_TITLE, CANNOT_FORECAST_SHORT, FEATURE_REQUIRES_SERVER_NEWER_THAN, INSUFFICIENT_FORECAST_DATA_SENTENCE, INSUFFICIENT_FORECAST_DATA_SHORT, LIGHTHOUSE_IS_REACHABLE, NOT_SENT, NOT_SET, NO_DATA_YET, OVERDUE_SHORT, OVER_TIME_EMPTY_SENTENCE, PREDICTABILITY_SCORE_EXPLANATION, REFINEMENT_ANSWERS, SECRET_NOT_SHOWN, SEEDED_TERMS, SLE_RISK_AT_RISK_FROM, STANDALONE_VOTER_KEY_SCOPE, UNKNOWN_SHAPE_NOTE, USAGE_DATA_BUDGET_MS, VOTER_KEY_HEADER, WORK_TRACKING_CONNECTION_LIST_HEADINGS, WORK_TRACKING_OPTION_HEADINGS, countNumberedRows, createFileUsageDataStore, createFileVoterKeyStore, createLighthouseAuthContext, createLighthouseClient, daysInRange, deliveryLikelihoodAnswer, describeAnswer, describeArchivedDeliveriesTitle, describeArchivedDeliveryHeadings, describeArchivedDeliveryRow, describeArrivalsDays, describeAsOfHeading, describeBacktestActual, describeBacktestPeriod, describeBacktestSummary, describeBlackoutRuleCount, describeBlackoutRuleSchedule, describeBlackoutRuleWriteConfirmation, describeBlockedDays, describeBlockedNow, describeBlockedOverTime, describeConnectionName, describeConnectionSummary, describeConnectionType, describeCycleTimeDays, describeDays, describeDeliveryChanceHeadings, describeDeliveryChanceRow, describeDeliveryCount, describeDeliveryDone, describeDeliveryFeatureHeadings, describeDeliveryFeatureRow, describeDeliveryLikelihood, describeDeliveryListHeadings, describeDeliveryListTitle, describeDeliveryMetricsHeading, describeDeliveryRow, describeFeatureCompletion, describeFeatureCount, describeFeatureListCount, describeFeatureListHeadings, describeFeatureProgress, describeFeatureRow, describeFeatureStart, describeFeatureTitle, describeFeatureWorkItemHeadings, describeFeatureWorkItemRow, describeFeatureWorkItemsHeading, describeHowManyTitle, describeInProgressNow, describeLastUpdated, describeManualForecastLikelihood, describeManualForecastSummary, describeMetricSummary, describeMetricsHeading, describeMissingCondition, describeNoBlackoutRules, describeNoDeliveries, describeNothingToTakeBack, describeOptionValue, describeOverTimeHeading, describeOwnerCount, describeOwnerListHeadings, describeOwnerListTitle, describeOwnerName, describeOwnerWriteConfirmation, describePercentileRows, describePercentilesOverTime, describePercentilesOverTimeDays, describePortfolioSummary, describePredictabilityScore, describePredictabilityScoreDays, describeProcessBehaviorChart, describeProcessBehaviorOverTime, describeProcessBehaviorOverTimeDays, describeReachable, describeReadiness, describeRecordedComment, describeRecordedDayHeadings, describeRecordedDayRow, describeRecordedDayTitle, describeRecordedVote, describeRefinementSummary, describeRefreshConfirmation, describeRefusedMetric, describeSleRiskNow, describeTags, describeTakenBack, describeTeamSummary, describeThroughputDays, describeTimeInState, describeTimeInStateContributorDays, describeTimeInStateDays, describeTotalArrivals, describeTotalThroughput, describeTotalWorkItemAge, describeTotalWorkItemAgeDays, describeUnknownMetric, describeVersion, describeVoteRefusal, describeVotes, describeWarnings, describeWhatWipLeavesUnsaid, describeWhenTitle, describeWipDays, describeWorkItemAgeDays, describeWorkItemAgePercentiles, describeWorkTrackingSystemCount, formatCalendarDay, formatLikelihood, formatTimestamp, getClientPackageContract, getDefaultMetricsDateRange, getStandaloneDiscoveryLockfilePath, getUsageDataStorePath, getVoterKeyScope, getVoterKeyStorePath, hideConnectionSecrets, isAPersonAtTheTerminal, isAtRiskOfMissingTheSle, isCalendarDay, isDoNotTrackSet, isMetricRefusal, isMissingItsCondition, isProcessBehaviorMetricType, isRefinementAnswer, isServerVersionNewerThan, keepVoterKey, latestRecordedDay, levelOf, likelihoodAnswer, loadStandaloneDiscoveryContract, metricsHeadlineLabel, mintVoterKey, myVoteOn, nameOrFallback, ordinalOf, parseStandaloneDiscoveryContract, placeActualAmongPercentiles, placeEnoughForLine, planUsageDataStep, pollCliAuthSession, processBehaviorChartTitle, queryServerAuthMode, readAnswerWording, readArchivedDeliveryItem, readArrivals, readBacktest, readBlackoutRules, readBlocked, readCumulativeStateTime, readCycleTime, readCycleTimeDefinitionName, readCycleTimePercentiles, readDeliveryList, readDeliveryMetricsHistory, readFeatureList, readFeatureWording, readFeatureWorkItems, readInProgressItems, readManualForecast, readMetricAnswer, readMetricsSubject, readNameOfMyVote, readOwnerList, readPercentilesOverTime, readPortfolio, readPortfolioDeliveries, readPredictabilityScore, readProcessBehaviorChart, readProcessBehaviorOverTime, readRefinementTerms, readRefinementWording, readRunChart, readServiceLevelExpectation, readSleRisk, readStoredUsageDataAnswer, readSystemWipLimit, readTeam, readTerms, readThroughput, readTimeInStateBar, readTimeInStateContributors, readTotalWorkItemAge, readUsageDataState, readVoteRefusal, readWip, readWorkItemAge, readWorkItemAgePercentiles, readWorkTrackingConnection, readWorkTrackingConnections, readWrittenBlackoutRule, readWrittenOwner, refinementDayVerdictOf, resolveTerms, settleUsageDataStep, sizingMomentOf, startCliAuthSession, summariseDeliveryMetricsHistory, switchUsageDataOn, timeInStateItemCount, usageDataStoreFor, validateLighthouseConnectivity, voterKeyStoreFor, withdrawUsageData };
3794
+ export { BLACKOUT_RULE_LIST_HEADINGS, BLACKOUT_RULE_LIST_TITLE, CANNOT_FORECAST_SHORT, FEATURE_REQUIRES_SERVER_NEWER_THAN, INSUFFICIENT_FORECAST_DATA_SENTENCE, INSUFFICIENT_FORECAST_DATA_SHORT, LIGHTHOUSE_IS_REACHABLE, NOT_SENT, NOT_SET, NO_DATA_YET, OVERDUE_SHORT, OVER_TIME_EMPTY_SENTENCE, PREDICTABILITY_SCORE_EXPLANATION, REFINEMENT_ANSWERS, SECRET_NOT_SHOWN, SEEDED_TERMS, SLE_RISK_AT_RISK_FROM, STANDALONE_VOTER_KEY_SCOPE, UNKNOWN_SHAPE_NOTE, USAGE_DATA_BUDGET_MS, VOTER_KEY_HEADER, WORK_TRACKING_CONNECTION_LIST_HEADINGS, WORK_TRACKING_OPTION_HEADINGS, countNumberedRows, createFileUsageDataStore, createFileVoterKeyStore, createLighthouseAuthContext, createLighthouseClient, daysInRange, deliveryLikelihoodAnswer, describeAnswer, describeArchivedDeliveriesTitle, describeArchivedDeliveryHeadings, describeArchivedDeliveryRow, describeArrivalsDays, describeAsOfHeading, describeBacktestActual, describeBacktestPeriod, describeBacktestSummary, describeBlackoutRuleCount, describeBlackoutRuleSchedule, describeBlackoutRuleWriteConfirmation, describeBlockedDays, describeBlockedNow, describeBlockedOverTime, describeConnectionName, describeConnectionSummary, describeConnectionType, describeCycleTimeDays, describeDays, describeDeliveryChanceHeadings, describeDeliveryChanceRow, describeDeliveryCount, describeDeliveryDone, describeDeliveryFeatureHeadings, describeDeliveryFeatureRow, describeDeliveryLikelihood, describeDeliveryListHeadings, describeDeliveryListTitle, describeDeliveryMetricsHeading, describeDeliveryRow, describeFeatureCompletion, describeFeatureCount, describeFeatureListCount, describeFeatureListHeadings, describeFeatureProgress, describeFeatureRow, describeFeatureStart, describeFeatureTitle, describeFeatureWorkItemHeadings, describeFeatureWorkItemRow, describeFeatureWorkItemsHeading, describeHowManyTitle, describeInProgressNow, describeLastUpdated, describeManualForecastLikelihood, describeManualForecastSummary, describeMetricSummary, describeMetricsHeading, describeMissingCondition, describeNoBlackoutRules, describeNoDeliveries, describeNothingToTakeBack, describeOptionValue, describeOverTimeHeading, describeOwnerCount, describeOwnerListHeadings, describeOwnerListTitle, describeOwnerName, describeOwnerWriteConfirmation, describePercentileDate, describePercentileDay, describePercentileRows, describePercentilesOverTime, describePercentilesOverTimeDays, describePortfolioSummary, describePredictabilityScore, describePredictabilityScoreDays, describeProcessBehaviorChart, describeProcessBehaviorOverTime, describeProcessBehaviorOverTimeDays, describeReachable, describeReadiness, describeRecordedComment, describeRecordedDayHeadings, describeRecordedDayRow, describeRecordedDayTitle, describeRecordedVote, describeRefinementSummary, describeRefreshConfirmation, describeRefusedMetric, describeReportListSummary, describeReportOwner, describeReportRefusal, describeReportSummary, describeSleRiskNow, describeStaleNow, describeTags, describeTakenBack, describeTeamSummary, describeThroughputDays, describeTimeInState, describeTimeInStateContributorDays, describeTimeInStateDays, describeTotalArrivals, describeTotalThroughput, describeTotalWorkItemAge, describeTotalWorkItemAgeDays, describeUnknownMetric, describeVersion, describeVoteRefusal, describeVotes, describeWarnings, describeWhatWipLeavesUnsaid, describeWhenTitle, describeWipDays, describeWorkItemAgeDays, describeWorkItemAgePercentiles, describeWorkTrackingSystemCount, formatCalendarDay, formatLikelihood, formatTimestamp, getClientPackageContract, getDefaultMetricsDateRange, getStandaloneDiscoveryLockfilePath, getUsageDataStorePath, getVoterKeyScope, getVoterKeyStorePath, hideConnectionSecrets, isAPersonAtTheTerminal, isAtRiskOfMissingTheSle, isCalendarDay, isDoNotTrackSet, isMetricRefusal, isMissingItsCondition, isProcessBehaviorMetricType, isRefinementAnswer, isServerVersionNewerThan, keepVoterKey, latestRecordedDay, levelOf, likelihoodAnswer, loadStandaloneDiscoveryContract, metricsHeadlineLabel, mintVoterKey, moreThanYearsText, myVoteOn, nameOrFallback, ordinalOf, parseStandaloneDiscoveryContract, placeActualAmongPercentiles, placeEnoughForLine, planUsageDataStep, pollCliAuthSession, processBehaviorChartTitle, queryServerAuthMode, readAnswerWording, readArchivedDeliveryItem, readArrivals, readBacktest, readBlackoutRules, readBlocked, readCumulativeStateTime, readCycleTime, readCycleTimeDefinitionName, readCycleTimePercentiles, readDeliveryList, readDeliveryMetricsHistory, readFeatureList, readFeatureWording, readFeatureWorkItems, readInProgressItems, readManualForecast, readMetricAnswer, readMetricsSubject, readNameOfMyVote, readOwnerList, readOwnersReport, readOwnersReports, readPercentilesOverTime, readPortfolio, readPortfolioDeliveries, readPredictabilityScore, readProcessBehaviorChart, readProcessBehaviorOverTime, readRefinementTerms, readRefinementWording, readReport, readReportList, readReportOwner, readReportRefusal, readRunChart, readServiceLevelExpectation, readSleRisk, readStoredUsageDataAnswer, readSystemWipLimit, readTeam, readTerms, readThroughput, readTimeInStateBar, readTimeInStateContributors, readTotalWorkItemAge, readUsageDataState, readVoteRefusal, readWip, readWorkItemAge, readWorkItemAgePercentiles, readWorkTrackingConnection, readWorkTrackingConnections, readWrittenBlackoutRule, readWrittenOwner, refinementDayVerdictOf, reportOpenedOccurrencesOf, resolveTerms, settleUsageDataStep, sizingMomentOf, startCliAuthSession, summariseDeliveryMetricsHistory, summariseReport, summariseReportList, switchUsageDataOn, timeInStateItemCount, usageDataStoreFor, validateLighthouseConnectivity, voterKeyStoreFor, withdrawUsageData, yearsBeyondHorizon };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letpeoplework/lighthouse-client",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "Shared Lighthouse API client contracts",
5
5
  "repository": {
6
6
  "type": "git",