@letpeoplework/lighthouse-client 1.11.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.cjs +142 -1
- package/dist/index.d.cts +101 -1
- package/dist/index.d.ts +101 -1
- package/dist/index.js +130 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,20 @@ const PROCESS_BEHAVIOR_CHART_ROUTES = {
|
|
|
37
37
|
const isProcessBehaviorMetricType = (value) => Object.hasOwn(PROCESS_BEHAVIOR_CHART_ROUTES, value);
|
|
38
38
|
//#endregion
|
|
39
39
|
//#region src/usageData.ts
|
|
40
|
+
const reportTemplateWeDisclose = { "then-and-now": "ThenAndNow" };
|
|
41
|
+
/**
|
|
42
|
+
* The opening of a report Lighthouse sent: its type and nothing else about it. A refused read, or a report of a
|
|
43
|
+
* type this version does not know, counts nothing.
|
|
44
|
+
*/
|
|
45
|
+
const reportOpenedOccurrencesOf = (answered) => {
|
|
46
|
+
if (!answered.ok || !isRecord$1(answered.value)) return [];
|
|
47
|
+
const { templateKey } = answered.value;
|
|
48
|
+
const reportTemplate = Object.entries(reportTemplateWeDisclose).find(([key]) => key === templateKey)?.[1];
|
|
49
|
+
return reportTemplate === void 0 ? [] : [{
|
|
50
|
+
name: "ReportOpened",
|
|
51
|
+
reportTemplate
|
|
52
|
+
}];
|
|
53
|
+
};
|
|
40
54
|
/**
|
|
41
55
|
* When a vote was cast, from Lighthouse's answer rather than this machine's clock: Lighthouse counts days in
|
|
42
56
|
* the instance's time zone and knows which cadence days are blacked out. The web counts it the same way.
|
|
@@ -2165,6 +2179,114 @@ const readNameOfMyVote = async (client, teamId, workItem, voterKey) => {
|
|
|
2165
2179
|
return log.ok ? nameOfMyVote(log.value) : null;
|
|
2166
2180
|
};
|
|
2167
2181
|
//#endregion
|
|
2182
|
+
//#region src/reportWording.ts
|
|
2183
|
+
const readWindow = (value) => isRecord(value) && isDay(value.start) && isDay(value.end) ? {
|
|
2184
|
+
start: value.start,
|
|
2185
|
+
end: value.end
|
|
2186
|
+
} : null;
|
|
2187
|
+
/** The report's name and windows, or null when the answer does not carry all three. */
|
|
2188
|
+
const readReport = (value) => {
|
|
2189
|
+
if (!isRecord(value) || !isRecord(value.thenAndNow)) return null;
|
|
2190
|
+
const name = textOf(value.name);
|
|
2191
|
+
const thenWindow = readWindow(value.thenAndNow.thenWindow);
|
|
2192
|
+
const nowWindow = readWindow(value.thenAndNow.nowWindow);
|
|
2193
|
+
if (name === void 0 || thenWindow === null || nowWindow === null) return null;
|
|
2194
|
+
return {
|
|
2195
|
+
name,
|
|
2196
|
+
thenWindow,
|
|
2197
|
+
nowWindow
|
|
2198
|
+
};
|
|
2199
|
+
};
|
|
2200
|
+
const readReportListItem = (value) => {
|
|
2201
|
+
if (!isRecord(value) || typeof value.id !== "number") return null;
|
|
2202
|
+
const name = textOf(value.name);
|
|
2203
|
+
if (name === void 0) return null;
|
|
2204
|
+
return {
|
|
2205
|
+
id: value.id,
|
|
2206
|
+
name,
|
|
2207
|
+
templateKey: textOf(value.templateKey),
|
|
2208
|
+
createdOn: textOf(value.createdOn)
|
|
2209
|
+
};
|
|
2210
|
+
};
|
|
2211
|
+
/**
|
|
2212
|
+
* Every report in the list, or null when the answer holds no list or any one report comes without its id or
|
|
2213
|
+
* name: a row that cannot say which report it is would misname the whole list.
|
|
2214
|
+
*/
|
|
2215
|
+
const readReportList = (value) => {
|
|
2216
|
+
if (!isRecord(value) || !Array.isArray(value.reports)) return null;
|
|
2217
|
+
const items = value.reports.map(readReportListItem);
|
|
2218
|
+
return items.every((item) => item !== null) ? items : null;
|
|
2219
|
+
};
|
|
2220
|
+
const ownerTerm$1 = (kind, terms) => kind === "team" ? terms.team : terms.portfolio;
|
|
2221
|
+
/** The owner as the instance names it, "Team Lightspeed", or by its id when its name could not be read. */
|
|
2222
|
+
const describeReportOwner = (kind, id, owner, terms) => {
|
|
2223
|
+
const term = ownerTerm$1(kind, terms);
|
|
2224
|
+
const name = isRecord(owner) ? textOf(owner.name) : void 0;
|
|
2225
|
+
return name === void 0 ? `${term} [id: ${id}]` : `${term} ${name}`;
|
|
2226
|
+
};
|
|
2227
|
+
const describeWindow = (label, window) => `${label} ${dayOf(window.start)} – ${dayOf(window.end)}`;
|
|
2228
|
+
/** The report's name, its owner and its two windows, one to a line. */
|
|
2229
|
+
const describeReportSummary = (report, owner) => [
|
|
2230
|
+
report.name,
|
|
2231
|
+
owner,
|
|
2232
|
+
`${describeWindow("Then", report.thenWindow)} · ${describeWindow("Now", report.nowWindow)}`
|
|
2233
|
+
].join("\n");
|
|
2234
|
+
const describeReportCount = (count) => {
|
|
2235
|
+
if (count === 0) return "No reports";
|
|
2236
|
+
return count === 1 ? "1 report" : `${count} reports`;
|
|
2237
|
+
};
|
|
2238
|
+
const describeReportListItem = (item) => [
|
|
2239
|
+
`${item.name} [id: ${item.id}]`,
|
|
2240
|
+
item.templateKey,
|
|
2241
|
+
item.createdOn === void 0 ? void 0 : `created ${dayOf(item.createdOn)}`
|
|
2242
|
+
].filter((part) => part !== void 0).join(" · ");
|
|
2243
|
+
/** How many reports the owner has, then each report's name, type and created day. */
|
|
2244
|
+
const describeReportListSummary = (reports, owner) => [`${owner} · ${describeReportCount(reports.length)}`, ...reports.map(describeReportListItem)].join("\n");
|
|
2245
|
+
const summariseReport = (value, owner) => {
|
|
2246
|
+
const report = readReport(value);
|
|
2247
|
+
return report === null ? null : describeReportSummary(report, owner);
|
|
2248
|
+
};
|
|
2249
|
+
const summariseReportList = (value, owner) => {
|
|
2250
|
+
const reports = readReportList(value);
|
|
2251
|
+
return reports === null ? null : describeReportListSummary(reports, owner);
|
|
2252
|
+
};
|
|
2253
|
+
const FORBIDDEN = 403;
|
|
2254
|
+
const NOT_FOUND = 404;
|
|
2255
|
+
const NOTHING_THERE = {
|
|
2256
|
+
list: (owner) => `There is no such ${owner}.`,
|
|
2257
|
+
report: (owner) => `There is no such report for that ${owner}.`
|
|
2258
|
+
};
|
|
2259
|
+
/**
|
|
2260
|
+
* Why a report or a list could not be read, in words the reader can act on: the web's sentence where it has
|
|
2261
|
+
* one. Any other refusal, the client's own "upgrade Lighthouse" among them, keeps its category and reason.
|
|
2262
|
+
*/
|
|
2263
|
+
const describeReportRefusal = (error, kind, read, terms) => {
|
|
2264
|
+
if (error.statusCode === FORBIDDEN) return `You have no access to that ${ownerTerm$1(kind, terms)}'s reports.`;
|
|
2265
|
+
if (error.problemCode === "template-not-supported") return "This report was made by a newer version of Lighthouse and can't be shown here.";
|
|
2266
|
+
if (error.statusCode === NOT_FOUND) return NOTHING_THERE[read](ownerTerm$1(kind, terms));
|
|
2267
|
+
return `${error.category}: ${error.reason}`;
|
|
2268
|
+
};
|
|
2269
|
+
/**
|
|
2270
|
+
* {@link describeReportRefusal} in the instance's own words. A refusal the client made before asking, as for a
|
|
2271
|
+
* Lighthouse too old for reports, asks that Lighthouse nothing more, not even its words.
|
|
2272
|
+
*/
|
|
2273
|
+
const readReportRefusal = async (source, error, kind, read) => describeReportRefusal(error, kind, read, error.statusCode === void 0 ? SEEDED_TERMS : await readTerms(source));
|
|
2274
|
+
//#endregion
|
|
2275
|
+
//#region src/reportReads.ts
|
|
2276
|
+
/** The owner's list of reports, exactly as Lighthouse answers it. */
|
|
2277
|
+
const readOwnersReports = (reads, owner) => owner.kind === "team" ? reads.getTeamReports(owner.id) : reads.getPortfolioReports(owner.id);
|
|
2278
|
+
/** One of the owner's reports, exactly as Lighthouse answers it. */
|
|
2279
|
+
const readOwnersReport = (reads, owner, reportId) => owner.kind === "team" ? reads.getTeamReport(owner.id, reportId) : reads.getPortfolioReport(owner.id, reportId);
|
|
2280
|
+
/**
|
|
2281
|
+
* {@link describeReportOwner} for an owner read from Lighthouse. Its name only labels a summary, so an owner that
|
|
2282
|
+
* cannot be read is named by its id instead, and this never fails.
|
|
2283
|
+
*/
|
|
2284
|
+
const readReportOwner = async (source, owner) => {
|
|
2285
|
+
const read = owner.kind === "team" ? source.getTeam(owner.id) : source.getPortfolio(owner.id);
|
|
2286
|
+
const [terms, named] = await Promise.all([readTerms(source), read.then((answer) => answer.ok ? answer.value : void 0, () => void 0)]);
|
|
2287
|
+
return describeReportOwner(owner.kind, owner.id, named, terms);
|
|
2288
|
+
};
|
|
2289
|
+
//#endregion
|
|
2168
2290
|
//#region src/usageDataReporter.ts
|
|
2169
2291
|
/** A command's own answer never waits on usage data for longer than this, whatever Lighthouse does. */
|
|
2170
2292
|
const USAGE_DATA_BUDGET_MS = 1e3;
|
|
@@ -3207,7 +3329,8 @@ const FEATURE_REQUIRES_SERVER_NEWER_THAN = {
|
|
|
3207
3329
|
sleRisk: "v26.9.19.10",
|
|
3208
3330
|
teamRefinement: "v26.10.3.6",
|
|
3209
3331
|
refinementVotes: "v26.10.3.6",
|
|
3210
|
-
staleness: "v26.10.16.6"
|
|
3332
|
+
staleness: "v26.10.16.6",
|
|
3333
|
+
reports: "v26.10.10.1"
|
|
3211
3334
|
};
|
|
3212
3335
|
/**
|
|
3213
3336
|
* Parses a Lighthouse version string ("v26.5.24.10", "26.5.24") into numeric
|
|
@@ -3269,6 +3392,7 @@ const createLighthouseClient = (configuration, dependencies = {}) => {
|
|
|
3269
3392
|
}
|
|
3270
3393
|
};
|
|
3271
3394
|
};
|
|
3395
|
+
const readReports = async (route) => await ensureServerSupports("reports") ?? requestJson(configuration, dependencies, route, { method: "GET" });
|
|
3272
3396
|
return {
|
|
3273
3397
|
checkConnectivity: async () => {
|
|
3274
3398
|
const fetchDependency = getFetchDependency(dependencies);
|
|
@@ -3345,6 +3469,10 @@ const createLighthouseClient = (configuration, dependencies = {}) => {
|
|
|
3345
3469
|
headers: voterKeyHeaders(options?.voterKey)
|
|
3346
3470
|
});
|
|
3347
3471
|
},
|
|
3472
|
+
getTeamReports: async (teamId) => readReports(`/v1/teams/${teamId}/reports`),
|
|
3473
|
+
getTeamReport: async (teamId, reportId) => readReports(`/v1/teams/${teamId}/reports/${reportId}`),
|
|
3474
|
+
getPortfolioReports: async (portfolioId) => readReports(`/v1/portfolios/${portfolioId}/reports`),
|
|
3475
|
+
getPortfolioReport: async (portfolioId, reportId) => readReports(`/v1/portfolios/${portfolioId}/reports/${reportId}`),
|
|
3348
3476
|
getTerminology: async () => requestJson(configuration, dependencies, "/v1/terminology/all", { method: "GET" }),
|
|
3349
3477
|
listPortfolios: async () => requestJson(configuration, dependencies, "/v1/portfolios", { method: "GET" }),
|
|
3350
3478
|
getPortfolio: async (portfolioId) => requestJson(configuration, dependencies, `/v1/portfolios/${portfolioId}`, { method: "GET" }),
|
|
@@ -3775,6 +3903,10 @@ exports.describeRecordedVote = describeRecordedVote;
|
|
|
3775
3903
|
exports.describeRefinementSummary = describeRefinementSummary;
|
|
3776
3904
|
exports.describeRefreshConfirmation = describeRefreshConfirmation;
|
|
3777
3905
|
exports.describeRefusedMetric = describeRefusedMetric;
|
|
3906
|
+
exports.describeReportListSummary = describeReportListSummary;
|
|
3907
|
+
exports.describeReportOwner = describeReportOwner;
|
|
3908
|
+
exports.describeReportRefusal = describeReportRefusal;
|
|
3909
|
+
exports.describeReportSummary = describeReportSummary;
|
|
3778
3910
|
exports.describeSleRiskNow = describeSleRiskNow;
|
|
3779
3911
|
exports.describeStaleNow = describeStaleNow;
|
|
3780
3912
|
exports.describeTags = describeTags;
|
|
@@ -3857,6 +3989,8 @@ exports.readMetricAnswer = readMetricAnswer;
|
|
|
3857
3989
|
exports.readMetricsSubject = readMetricsSubject;
|
|
3858
3990
|
exports.readNameOfMyVote = readNameOfMyVote;
|
|
3859
3991
|
exports.readOwnerList = readOwnerList;
|
|
3992
|
+
exports.readOwnersReport = readOwnersReport;
|
|
3993
|
+
exports.readOwnersReports = readOwnersReports;
|
|
3860
3994
|
exports.readPercentilesOverTime = readPercentilesOverTime;
|
|
3861
3995
|
exports.readPortfolio = readPortfolio;
|
|
3862
3996
|
exports.readPortfolioDeliveries = readPortfolioDeliveries;
|
|
@@ -3865,6 +3999,10 @@ exports.readProcessBehaviorChart = readProcessBehaviorChart;
|
|
|
3865
3999
|
exports.readProcessBehaviorOverTime = readProcessBehaviorOverTime;
|
|
3866
4000
|
exports.readRefinementTerms = readRefinementTerms;
|
|
3867
4001
|
exports.readRefinementWording = readRefinementWording;
|
|
4002
|
+
exports.readReport = readReport;
|
|
4003
|
+
exports.readReportList = readReportList;
|
|
4004
|
+
exports.readReportOwner = readReportOwner;
|
|
4005
|
+
exports.readReportRefusal = readReportRefusal;
|
|
3868
4006
|
exports.readRunChart = readRunChart;
|
|
3869
4007
|
exports.readServiceLevelExpectation = readServiceLevelExpectation;
|
|
3870
4008
|
exports.readSleRisk = readSleRisk;
|
|
@@ -3886,11 +4024,14 @@ exports.readWorkTrackingConnections = readWorkTrackingConnections;
|
|
|
3886
4024
|
exports.readWrittenBlackoutRule = readWrittenBlackoutRule;
|
|
3887
4025
|
exports.readWrittenOwner = readWrittenOwner;
|
|
3888
4026
|
exports.refinementDayVerdictOf = refinementDayVerdictOf;
|
|
4027
|
+
exports.reportOpenedOccurrencesOf = reportOpenedOccurrencesOf;
|
|
3889
4028
|
exports.resolveTerms = resolveTerms;
|
|
3890
4029
|
exports.settleUsageDataStep = settleUsageDataStep;
|
|
3891
4030
|
exports.sizingMomentOf = sizingMomentOf;
|
|
3892
4031
|
exports.startCliAuthSession = startCliAuthSession;
|
|
3893
4032
|
exports.summariseDeliveryMetricsHistory = summariseDeliveryMetricsHistory;
|
|
4033
|
+
exports.summariseReport = summariseReport;
|
|
4034
|
+
exports.summariseReportList = summariseReportList;
|
|
3894
4035
|
exports.switchUsageDataOn = switchUsageDataOn;
|
|
3895
4036
|
exports.timeInStateItemCount = timeInStateItemCount;
|
|
3896
4037
|
exports.usageDataStoreFor = usageDataStoreFor;
|
package/dist/index.d.cts
CHANGED
|
@@ -8,8 +8,10 @@ export type PlainUsageDataEventName = "TeamCreated" | "TeamDeleted" | "Portfolio
|
|
|
8
8
|
export type SizingUsageDataEventName = "TeamSizingVoteCast" | "TeamSizingReadinessReached";
|
|
9
9
|
/** The usage event that says which verdict a Team's Refinement showed on its Refinement day. */
|
|
10
10
|
export type VerdictUsageDataEventName = "TeamRefinementDayVerdictShown";
|
|
11
|
+
/** The usage event that says a report was read, and of which type. */
|
|
12
|
+
export type ReportUsageDataEventName = "ReportOpened";
|
|
11
13
|
/** The usage events a client reports, by the names Lighthouse already counts for the web. */
|
|
12
|
-
export type UsageDataEventName = PlainUsageDataEventName | SizingUsageDataEventName | VerdictUsageDataEventName;
|
|
14
|
+
export type UsageDataEventName = PlainUsageDataEventName | SizingUsageDataEventName | VerdictUsageDataEventName | ReportUsageDataEventName;
|
|
13
15
|
/** Fewer Work Items ready than needed, enough, more than enough, or no number at all. */
|
|
14
16
|
export type UsageDataRefinementVerdict = "Below" | "In" | "Above" | "None";
|
|
15
17
|
export type UsageDataSizingMoment = "NoCadence" | "OnRefinementDay" | "OnOtherDay";
|
|
@@ -22,7 +24,19 @@ export type UsageDataOccurrence = {
|
|
|
22
24
|
} | {
|
|
23
25
|
readonly name: VerdictUsageDataEventName;
|
|
24
26
|
readonly refinementVerdict: UsageDataRefinementVerdict;
|
|
27
|
+
} | {
|
|
28
|
+
readonly name: ReportUsageDataEventName;
|
|
29
|
+
readonly reportTemplate: UsageDataReportTemplate;
|
|
25
30
|
};
|
|
31
|
+
/** A report's type as Lighthouse names it when it sends the report. */
|
|
32
|
+
export type ReportTemplateKey = "then-and-now";
|
|
33
|
+
/** A report's type in the words usage data publishes, the same the web uses. */
|
|
34
|
+
export type UsageDataReportTemplate = "ThenAndNow";
|
|
35
|
+
/**
|
|
36
|
+
* The opening of a report Lighthouse sent: its type and nothing else about it. A refused read, or a report of a
|
|
37
|
+
* type this version does not know, counts nothing.
|
|
38
|
+
*/
|
|
39
|
+
export declare const reportOpenedOccurrencesOf: (answered: LighthouseApiResult<unknown>) => readonly UsageDataOccurrence[];
|
|
26
40
|
/** What Lighthouse's answer about a Team's Refinement says about today. */
|
|
27
41
|
export type RefinementMomentFacts = {
|
|
28
42
|
readonly nextRefinementDate: string | null;
|
|
@@ -1051,6 +1065,86 @@ export declare const myVoteOn: (refinement: Pick<TeamRefinement, "workItems">, w
|
|
|
1051
1065
|
/** {@link nameOfMyVote}, read from Lighthouse; null when the log cannot be read either. */
|
|
1052
1066
|
export declare const readNameOfMyVote: (client: Pick<LighthouseClient, "getRefinementLog">, teamId: number, workItem: string, voterKey: string | undefined) => Promise<string | null>;
|
|
1053
1067
|
//#endregion
|
|
1068
|
+
//#region src/reportWording.d.ts
|
|
1069
|
+
/** Who a report belongs to: a Team or a Portfolio. */
|
|
1070
|
+
export type ReportOwnerKind = "team" | "portfolio";
|
|
1071
|
+
/** The Team or Portfolio whose reports are read, by its id. */
|
|
1072
|
+
export type ReportOwner = {
|
|
1073
|
+
readonly kind: ReportOwnerKind;
|
|
1074
|
+
readonly id: number;
|
|
1075
|
+
};
|
|
1076
|
+
/** A window of days as Lighthouse sends it: its first and its last day. */
|
|
1077
|
+
export type ReportWindow = {
|
|
1078
|
+
readonly start: string;
|
|
1079
|
+
readonly end: string;
|
|
1080
|
+
};
|
|
1081
|
+
/** What a report's summary says: its name and its two windows. */
|
|
1082
|
+
export type ReportView = {
|
|
1083
|
+
readonly name: string;
|
|
1084
|
+
readonly thenWindow: ReportWindow;
|
|
1085
|
+
readonly nowWindow: ReportWindow;
|
|
1086
|
+
};
|
|
1087
|
+
/** One report as a list row shows it. Fields Lighthouse did not send stay undefined. */
|
|
1088
|
+
export type ReportListItem = {
|
|
1089
|
+
readonly id: number;
|
|
1090
|
+
readonly name: string;
|
|
1091
|
+
readonly templateKey: string | undefined;
|
|
1092
|
+
readonly createdOn: string | undefined;
|
|
1093
|
+
};
|
|
1094
|
+
/** The report's name and windows, or null when the answer does not carry all three. */
|
|
1095
|
+
export declare const readReport: (value: unknown) => ReportView | null;
|
|
1096
|
+
/**
|
|
1097
|
+
* Every report in the list, or null when the answer holds no list or any one report comes without its id or
|
|
1098
|
+
* name: a row that cannot say which report it is would misname the whole list.
|
|
1099
|
+
*/
|
|
1100
|
+
export declare const readReportList: (value: unknown) => ReportListItem[] | null;
|
|
1101
|
+
/** The owner as the instance names it, "Team Lightspeed", or by its id when its name could not be read. */
|
|
1102
|
+
export declare const describeReportOwner: (kind: ReportOwnerKind, id: number, owner: unknown, terms: Terms) => string;
|
|
1103
|
+
/** The report's name, its owner and its two windows, one to a line. */
|
|
1104
|
+
export declare const describeReportSummary: (report: ReportView, owner: string) => string;
|
|
1105
|
+
/** How many reports the owner has, then each report's name, type and created day. */
|
|
1106
|
+
export declare const describeReportListSummary: (reports: readonly ReportListItem[], owner: string) => string;
|
|
1107
|
+
/** A summary of Lighthouse's answer, said of its owner; null when the answer is not one the summary can read. */
|
|
1108
|
+
export type ReportSummariser = (value: unknown, owner: string) => string | null;
|
|
1109
|
+
export declare const summariseReport: ReportSummariser;
|
|
1110
|
+
export declare const summariseReportList: ReportSummariser;
|
|
1111
|
+
/** What was read: the owner's list of reports, or one report. */
|
|
1112
|
+
export type ReportRead = "list" | "report";
|
|
1113
|
+
/**
|
|
1114
|
+
* Why a report or a list could not be read, in words the reader can act on: the web's sentence where it has
|
|
1115
|
+
* one. Any other refusal, the client's own "upgrade Lighthouse" among them, keeps its category and reason.
|
|
1116
|
+
*/
|
|
1117
|
+
export declare const describeReportRefusal: (error: LighthouseApiError, kind: ReportOwnerKind, read: ReportRead, terms: Terms) => string;
|
|
1118
|
+
/**
|
|
1119
|
+
* {@link describeReportRefusal} in the instance's own words. A refusal the client made before asking, as for a
|
|
1120
|
+
* Lighthouse too old for reports, asks that Lighthouse nothing more, not even its words.
|
|
1121
|
+
*/
|
|
1122
|
+
export declare const readReportRefusal: (source: TermsSource, error: LighthouseApiError, kind: ReportOwnerKind, read: ReportRead) => Promise<string>;
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/reportReads.d.ts
|
|
1125
|
+
/** The four report reads, a Team's and a Portfolio's list and one report of each. */
|
|
1126
|
+
export type ReportReads = Pick<LighthouseClient, "getTeamReports" | "getTeamReport" | "getPortfolioReports" | "getPortfolioReport">;
|
|
1127
|
+
/** The owner's list of reports, exactly as Lighthouse answers it. */
|
|
1128
|
+
export declare const readOwnersReports: (reads: ReportReads, owner: ReportOwner) => Promise<LighthouseApiResult<unknown>>;
|
|
1129
|
+
/** One of the owner's reports, exactly as Lighthouse answers it. */
|
|
1130
|
+
export declare const readOwnersReport: (reads: ReportReads, owner: ReportOwner, reportId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1131
|
+
type OwnerRead = (id: number) => Promise<{
|
|
1132
|
+
readonly ok: true;
|
|
1133
|
+
readonly value: unknown;
|
|
1134
|
+
} | {
|
|
1135
|
+
readonly ok: false;
|
|
1136
|
+
}>;
|
|
1137
|
+
/** Where the owner's name and the instance's words are read from. */
|
|
1138
|
+
export type ReportOwnerSource = TermsSource & {
|
|
1139
|
+
readonly getTeam: OwnerRead;
|
|
1140
|
+
readonly getPortfolio: OwnerRead;
|
|
1141
|
+
};
|
|
1142
|
+
/**
|
|
1143
|
+
* {@link describeReportOwner} for an owner read from Lighthouse. Its name only labels a summary, so an owner that
|
|
1144
|
+
* cannot be read is named by its id instead, and this never fails.
|
|
1145
|
+
*/
|
|
1146
|
+
export declare const readReportOwner: (source: ReportOwnerSource, owner: ReportOwner) => Promise<string>;
|
|
1147
|
+
//#endregion
|
|
1054
1148
|
//#region src/usageDataStore.d.ts
|
|
1055
1149
|
/** The answer kept for a Lighthouse, undefined when never asked there, or "unreadable" when the file is not ours. */
|
|
1056
1150
|
export type UsageDataStoreReading = StoredUsageDataAnswer | undefined | "unreadable";
|
|
@@ -1799,6 +1893,11 @@ export type LighthouseClient = {
|
|
|
1799
1893
|
readonly addRefinementComment: (teamId: number, workItem: string, comment: RefinementCommentInput) => Promise<LighthouseApiResult<VotedRow>>;
|
|
1800
1894
|
readonly takeBackRefinementVote: (teamId: number, workItem: string, takeBack: RefinementTakeBackInput) => Promise<LighthouseApiResult<VotedRow>>;
|
|
1801
1895
|
readonly getRefinementLog: (teamId: number, workItem: string, options?: RefinementReadOptions) => Promise<LighthouseApiResult<SizingLog>>;
|
|
1896
|
+
/** A report list or a report exactly as Lighthouse answers it, so nothing on the way rounds or judges a value. */
|
|
1897
|
+
readonly getTeamReports: (teamId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1898
|
+
readonly getTeamReport: (teamId: number, reportId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1899
|
+
readonly getPortfolioReports: (portfolioId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1900
|
+
readonly getPortfolioReport: (portfolioId: number, reportId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1802
1901
|
readonly getTerminology: () => Promise<LighthouseApiResult<readonly TerminologyEntry[]>>;
|
|
1803
1902
|
readonly listPortfolios: () => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
1804
1903
|
readonly getPortfolio: (portfolioId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
@@ -1897,6 +1996,7 @@ export declare const FEATURE_REQUIRES_SERVER_NEWER_THAN: {
|
|
|
1897
1996
|
readonly teamRefinement: "v26.10.3.6";
|
|
1898
1997
|
readonly refinementVotes: "v26.10.3.6";
|
|
1899
1998
|
readonly staleness: "v26.10.16.6";
|
|
1999
|
+
readonly reports: "v26.10.10.1";
|
|
1900
2000
|
};
|
|
1901
2001
|
/**
|
|
1902
2002
|
* Returns true when `candidate` is strictly newer than `baseline`, false when
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ export type PlainUsageDataEventName = "TeamCreated" | "TeamDeleted" | "Portfolio
|
|
|
8
8
|
export type SizingUsageDataEventName = "TeamSizingVoteCast" | "TeamSizingReadinessReached";
|
|
9
9
|
/** The usage event that says which verdict a Team's Refinement showed on its Refinement day. */
|
|
10
10
|
export type VerdictUsageDataEventName = "TeamRefinementDayVerdictShown";
|
|
11
|
+
/** The usage event that says a report was read, and of which type. */
|
|
12
|
+
export type ReportUsageDataEventName = "ReportOpened";
|
|
11
13
|
/** The usage events a client reports, by the names Lighthouse already counts for the web. */
|
|
12
|
-
export type UsageDataEventName = PlainUsageDataEventName | SizingUsageDataEventName | VerdictUsageDataEventName;
|
|
14
|
+
export type UsageDataEventName = PlainUsageDataEventName | SizingUsageDataEventName | VerdictUsageDataEventName | ReportUsageDataEventName;
|
|
13
15
|
/** Fewer Work Items ready than needed, enough, more than enough, or no number at all. */
|
|
14
16
|
export type UsageDataRefinementVerdict = "Below" | "In" | "Above" | "None";
|
|
15
17
|
export type UsageDataSizingMoment = "NoCadence" | "OnRefinementDay" | "OnOtherDay";
|
|
@@ -22,7 +24,19 @@ export type UsageDataOccurrence = {
|
|
|
22
24
|
} | {
|
|
23
25
|
readonly name: VerdictUsageDataEventName;
|
|
24
26
|
readonly refinementVerdict: UsageDataRefinementVerdict;
|
|
27
|
+
} | {
|
|
28
|
+
readonly name: ReportUsageDataEventName;
|
|
29
|
+
readonly reportTemplate: UsageDataReportTemplate;
|
|
25
30
|
};
|
|
31
|
+
/** A report's type as Lighthouse names it when it sends the report. */
|
|
32
|
+
export type ReportTemplateKey = "then-and-now";
|
|
33
|
+
/** A report's type in the words usage data publishes, the same the web uses. */
|
|
34
|
+
export type UsageDataReportTemplate = "ThenAndNow";
|
|
35
|
+
/**
|
|
36
|
+
* The opening of a report Lighthouse sent: its type and nothing else about it. A refused read, or a report of a
|
|
37
|
+
* type this version does not know, counts nothing.
|
|
38
|
+
*/
|
|
39
|
+
export declare const reportOpenedOccurrencesOf: (answered: LighthouseApiResult<unknown>) => readonly UsageDataOccurrence[];
|
|
26
40
|
/** What Lighthouse's answer about a Team's Refinement says about today. */
|
|
27
41
|
export type RefinementMomentFacts = {
|
|
28
42
|
readonly nextRefinementDate: string | null;
|
|
@@ -1051,6 +1065,86 @@ export declare const myVoteOn: (refinement: Pick<TeamRefinement, "workItems">, w
|
|
|
1051
1065
|
/** {@link nameOfMyVote}, read from Lighthouse; null when the log cannot be read either. */
|
|
1052
1066
|
export declare const readNameOfMyVote: (client: Pick<LighthouseClient, "getRefinementLog">, teamId: number, workItem: string, voterKey: string | undefined) => Promise<string | null>;
|
|
1053
1067
|
//#endregion
|
|
1068
|
+
//#region src/reportWording.d.ts
|
|
1069
|
+
/** Who a report belongs to: a Team or a Portfolio. */
|
|
1070
|
+
export type ReportOwnerKind = "team" | "portfolio";
|
|
1071
|
+
/** The Team or Portfolio whose reports are read, by its id. */
|
|
1072
|
+
export type ReportOwner = {
|
|
1073
|
+
readonly kind: ReportOwnerKind;
|
|
1074
|
+
readonly id: number;
|
|
1075
|
+
};
|
|
1076
|
+
/** A window of days as Lighthouse sends it: its first and its last day. */
|
|
1077
|
+
export type ReportWindow = {
|
|
1078
|
+
readonly start: string;
|
|
1079
|
+
readonly end: string;
|
|
1080
|
+
};
|
|
1081
|
+
/** What a report's summary says: its name and its two windows. */
|
|
1082
|
+
export type ReportView = {
|
|
1083
|
+
readonly name: string;
|
|
1084
|
+
readonly thenWindow: ReportWindow;
|
|
1085
|
+
readonly nowWindow: ReportWindow;
|
|
1086
|
+
};
|
|
1087
|
+
/** One report as a list row shows it. Fields Lighthouse did not send stay undefined. */
|
|
1088
|
+
export type ReportListItem = {
|
|
1089
|
+
readonly id: number;
|
|
1090
|
+
readonly name: string;
|
|
1091
|
+
readonly templateKey: string | undefined;
|
|
1092
|
+
readonly createdOn: string | undefined;
|
|
1093
|
+
};
|
|
1094
|
+
/** The report's name and windows, or null when the answer does not carry all three. */
|
|
1095
|
+
export declare const readReport: (value: unknown) => ReportView | null;
|
|
1096
|
+
/**
|
|
1097
|
+
* Every report in the list, or null when the answer holds no list or any one report comes without its id or
|
|
1098
|
+
* name: a row that cannot say which report it is would misname the whole list.
|
|
1099
|
+
*/
|
|
1100
|
+
export declare const readReportList: (value: unknown) => ReportListItem[] | null;
|
|
1101
|
+
/** The owner as the instance names it, "Team Lightspeed", or by its id when its name could not be read. */
|
|
1102
|
+
export declare const describeReportOwner: (kind: ReportOwnerKind, id: number, owner: unknown, terms: Terms) => string;
|
|
1103
|
+
/** The report's name, its owner and its two windows, one to a line. */
|
|
1104
|
+
export declare const describeReportSummary: (report: ReportView, owner: string) => string;
|
|
1105
|
+
/** How many reports the owner has, then each report's name, type and created day. */
|
|
1106
|
+
export declare const describeReportListSummary: (reports: readonly ReportListItem[], owner: string) => string;
|
|
1107
|
+
/** A summary of Lighthouse's answer, said of its owner; null when the answer is not one the summary can read. */
|
|
1108
|
+
export type ReportSummariser = (value: unknown, owner: string) => string | null;
|
|
1109
|
+
export declare const summariseReport: ReportSummariser;
|
|
1110
|
+
export declare const summariseReportList: ReportSummariser;
|
|
1111
|
+
/** What was read: the owner's list of reports, or one report. */
|
|
1112
|
+
export type ReportRead = "list" | "report";
|
|
1113
|
+
/**
|
|
1114
|
+
* Why a report or a list could not be read, in words the reader can act on: the web's sentence where it has
|
|
1115
|
+
* one. Any other refusal, the client's own "upgrade Lighthouse" among them, keeps its category and reason.
|
|
1116
|
+
*/
|
|
1117
|
+
export declare const describeReportRefusal: (error: LighthouseApiError, kind: ReportOwnerKind, read: ReportRead, terms: Terms) => string;
|
|
1118
|
+
/**
|
|
1119
|
+
* {@link describeReportRefusal} in the instance's own words. A refusal the client made before asking, as for a
|
|
1120
|
+
* Lighthouse too old for reports, asks that Lighthouse nothing more, not even its words.
|
|
1121
|
+
*/
|
|
1122
|
+
export declare const readReportRefusal: (source: TermsSource, error: LighthouseApiError, kind: ReportOwnerKind, read: ReportRead) => Promise<string>;
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/reportReads.d.ts
|
|
1125
|
+
/** The four report reads, a Team's and a Portfolio's list and one report of each. */
|
|
1126
|
+
export type ReportReads = Pick<LighthouseClient, "getTeamReports" | "getTeamReport" | "getPortfolioReports" | "getPortfolioReport">;
|
|
1127
|
+
/** The owner's list of reports, exactly as Lighthouse answers it. */
|
|
1128
|
+
export declare const readOwnersReports: (reads: ReportReads, owner: ReportOwner) => Promise<LighthouseApiResult<unknown>>;
|
|
1129
|
+
/** One of the owner's reports, exactly as Lighthouse answers it. */
|
|
1130
|
+
export declare const readOwnersReport: (reads: ReportReads, owner: ReportOwner, reportId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1131
|
+
type OwnerRead = (id: number) => Promise<{
|
|
1132
|
+
readonly ok: true;
|
|
1133
|
+
readonly value: unknown;
|
|
1134
|
+
} | {
|
|
1135
|
+
readonly ok: false;
|
|
1136
|
+
}>;
|
|
1137
|
+
/** Where the owner's name and the instance's words are read from. */
|
|
1138
|
+
export type ReportOwnerSource = TermsSource & {
|
|
1139
|
+
readonly getTeam: OwnerRead;
|
|
1140
|
+
readonly getPortfolio: OwnerRead;
|
|
1141
|
+
};
|
|
1142
|
+
/**
|
|
1143
|
+
* {@link describeReportOwner} for an owner read from Lighthouse. Its name only labels a summary, so an owner that
|
|
1144
|
+
* cannot be read is named by its id instead, and this never fails.
|
|
1145
|
+
*/
|
|
1146
|
+
export declare const readReportOwner: (source: ReportOwnerSource, owner: ReportOwner) => Promise<string>;
|
|
1147
|
+
//#endregion
|
|
1054
1148
|
//#region src/usageDataStore.d.ts
|
|
1055
1149
|
/** The answer kept for a Lighthouse, undefined when never asked there, or "unreadable" when the file is not ours. */
|
|
1056
1150
|
export type UsageDataStoreReading = StoredUsageDataAnswer | undefined | "unreadable";
|
|
@@ -1799,6 +1893,11 @@ export type LighthouseClient = {
|
|
|
1799
1893
|
readonly addRefinementComment: (teamId: number, workItem: string, comment: RefinementCommentInput) => Promise<LighthouseApiResult<VotedRow>>;
|
|
1800
1894
|
readonly takeBackRefinementVote: (teamId: number, workItem: string, takeBack: RefinementTakeBackInput) => Promise<LighthouseApiResult<VotedRow>>;
|
|
1801
1895
|
readonly getRefinementLog: (teamId: number, workItem: string, options?: RefinementReadOptions) => Promise<LighthouseApiResult<SizingLog>>;
|
|
1896
|
+
/** A report list or a report exactly as Lighthouse answers it, so nothing on the way rounds or judges a value. */
|
|
1897
|
+
readonly getTeamReports: (teamId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1898
|
+
readonly getTeamReport: (teamId: number, reportId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1899
|
+
readonly getPortfolioReports: (portfolioId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1900
|
+
readonly getPortfolioReport: (portfolioId: number, reportId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
1802
1901
|
readonly getTerminology: () => Promise<LighthouseApiResult<readonly TerminologyEntry[]>>;
|
|
1803
1902
|
readonly listPortfolios: () => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
1804
1903
|
readonly getPortfolio: (portfolioId: number) => Promise<LighthouseApiResult<unknown>>;
|
|
@@ -1897,6 +1996,7 @@ export declare const FEATURE_REQUIRES_SERVER_NEWER_THAN: {
|
|
|
1897
1996
|
readonly teamRefinement: "v26.10.3.6";
|
|
1898
1997
|
readonly refinementVotes: "v26.10.3.6";
|
|
1899
1998
|
readonly staleness: "v26.10.16.6";
|
|
1999
|
+
readonly reports: "v26.10.10.1";
|
|
1900
2000
|
};
|
|
1901
2001
|
/**
|
|
1902
2002
|
* Returns true when `candidate` is strictly newer than `baseline`, false when
|
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.
|
|
@@ -2164,6 +2178,114 @@ const readNameOfMyVote = async (client, teamId, workItem, voterKey) => {
|
|
|
2164
2178
|
return log.ok ? nameOfMyVote(log.value) : null;
|
|
2165
2179
|
};
|
|
2166
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
|
|
2167
2289
|
//#region src/usageDataReporter.ts
|
|
2168
2290
|
/** A command's own answer never waits on usage data for longer than this, whatever Lighthouse does. */
|
|
2169
2291
|
const USAGE_DATA_BUDGET_MS = 1e3;
|
|
@@ -3206,7 +3328,8 @@ const FEATURE_REQUIRES_SERVER_NEWER_THAN = {
|
|
|
3206
3328
|
sleRisk: "v26.9.19.10",
|
|
3207
3329
|
teamRefinement: "v26.10.3.6",
|
|
3208
3330
|
refinementVotes: "v26.10.3.6",
|
|
3209
|
-
staleness: "v26.10.16.6"
|
|
3331
|
+
staleness: "v26.10.16.6",
|
|
3332
|
+
reports: "v26.10.10.1"
|
|
3210
3333
|
};
|
|
3211
3334
|
/**
|
|
3212
3335
|
* Parses a Lighthouse version string ("v26.5.24.10", "26.5.24") into numeric
|
|
@@ -3268,6 +3391,7 @@ const createLighthouseClient = (configuration, dependencies = {}) => {
|
|
|
3268
3391
|
}
|
|
3269
3392
|
};
|
|
3270
3393
|
};
|
|
3394
|
+
const readReports = async (route) => await ensureServerSupports("reports") ?? requestJson(configuration, dependencies, route, { method: "GET" });
|
|
3271
3395
|
return {
|
|
3272
3396
|
checkConnectivity: async () => {
|
|
3273
3397
|
const fetchDependency = getFetchDependency(dependencies);
|
|
@@ -3344,6 +3468,10 @@ const createLighthouseClient = (configuration, dependencies = {}) => {
|
|
|
3344
3468
|
headers: voterKeyHeaders(options?.voterKey)
|
|
3345
3469
|
});
|
|
3346
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}`),
|
|
3347
3475
|
getTerminology: async () => requestJson(configuration, dependencies, "/v1/terminology/all", { method: "GET" }),
|
|
3348
3476
|
listPortfolios: async () => requestJson(configuration, dependencies, "/v1/portfolios", { method: "GET" }),
|
|
3349
3477
|
getPortfolio: async (portfolioId) => requestJson(configuration, dependencies, `/v1/portfolios/${portfolioId}`, { method: "GET" }),
|
|
@@ -3663,4 +3791,4 @@ const usageDataCalls = (configuration, dependencies) => {
|
|
|
3663
3791
|
};
|
|
3664
3792
|
};
|
|
3665
3793
|
//#endregion
|
|
3666
|
-
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, 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, 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, yearsBeyondHorizon };
|
|
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 };
|