@letpeoplework/lighthouse-client 0.7.0 → 1.0.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 +169 -0
- package/dist/index.d.cts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +167 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,8 @@ __export(index_exports, {
|
|
|
24
24
|
createLighthouseClient: () => createLighthouseClient,
|
|
25
25
|
getClientPackageContract: () => getClientPackageContract,
|
|
26
26
|
getDefaultMetricsDateRange: () => getDefaultMetricsDateRange,
|
|
27
|
+
getStandaloneDiscoveryLockfilePath: () => getStandaloneDiscoveryLockfilePath,
|
|
28
|
+
loadStandaloneDiscoveryContract: () => loadStandaloneDiscoveryContract,
|
|
27
29
|
parseStandaloneDiscoveryContract: () => parseStandaloneDiscoveryContract,
|
|
28
30
|
pollCliAuthSession: () => pollCliAuthSession,
|
|
29
31
|
queryServerAuthMode: () => queryServerAuthMode,
|
|
@@ -31,6 +33,9 @@ __export(index_exports, {
|
|
|
31
33
|
validateLighthouseConnectivity: () => validateLighthouseConnectivity
|
|
32
34
|
});
|
|
33
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
var import_promises = require("fs/promises");
|
|
37
|
+
var import_node_os = require("os");
|
|
38
|
+
var import_node_path = require("path");
|
|
34
39
|
var getClientPackageContract = () => ({
|
|
35
40
|
name: "@letpeoplework/lighthouse-client",
|
|
36
41
|
capabilities: [
|
|
@@ -41,6 +46,7 @@ var getClientPackageContract = () => ({
|
|
|
41
46
|
]
|
|
42
47
|
});
|
|
43
48
|
var SUPPORTED_DISCOVERY_CONTRACT_VERSION = 1;
|
|
49
|
+
var STANDALONE_DISCOVERY_LOCKFILE_NAME = "standalone.lock.json";
|
|
44
50
|
var isObjectRecord = (value) => {
|
|
45
51
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
52
|
};
|
|
@@ -155,6 +161,47 @@ var parseStandaloneDiscoveryContract = (serializedContract) => {
|
|
|
155
161
|
detectedAtUtc
|
|
156
162
|
});
|
|
157
163
|
};
|
|
164
|
+
var getStandaloneDiscoveryLockfilePath = () => {
|
|
165
|
+
if (process.env.LIGHTHOUSE_STANDALONE_LOCKFILE_PATH !== void 0) {
|
|
166
|
+
return process.env.LIGHTHOUSE_STANDALONE_LOCKFILE_PATH;
|
|
167
|
+
}
|
|
168
|
+
if (process.platform === "darwin") {
|
|
169
|
+
return (0, import_node_path.join)(
|
|
170
|
+
(0, import_node_os.homedir)(),
|
|
171
|
+
"Library",
|
|
172
|
+
"Application Support",
|
|
173
|
+
"Lighthouse",
|
|
174
|
+
STANDALONE_DISCOVERY_LOCKFILE_NAME
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
if (process.platform === "win32") {
|
|
178
|
+
return (0, import_node_path.join)(
|
|
179
|
+
process.env.APPDATA ?? (0, import_node_path.join)((0, import_node_os.homedir)(), "AppData", "Roaming"),
|
|
180
|
+
"Lighthouse",
|
|
181
|
+
STANDALONE_DISCOVERY_LOCKFILE_NAME
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
return (0, import_node_path.join)(
|
|
185
|
+
process.env.XDG_CONFIG_HOME ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".config"),
|
|
186
|
+
"Lighthouse",
|
|
187
|
+
STANDALONE_DISCOVERY_LOCKFILE_NAME
|
|
188
|
+
);
|
|
189
|
+
};
|
|
190
|
+
var loadStandaloneDiscoveryContract = async () => {
|
|
191
|
+
try {
|
|
192
|
+
const serializedContract = await (0, import_promises.readFile)(
|
|
193
|
+
getStandaloneDiscoveryLockfilePath(),
|
|
194
|
+
"utf8"
|
|
195
|
+
);
|
|
196
|
+
const parsedContract = parseStandaloneDiscoveryContract(serializedContract);
|
|
197
|
+
if (!parsedContract.isValid) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
return parsedContract.contract;
|
|
201
|
+
} catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
158
205
|
var getResolvedEndpoint = (mode, lighthouseUrl) => {
|
|
159
206
|
const apiBaseUrl = getApiBaseUrl(lighthouseUrl);
|
|
160
207
|
return {
|
|
@@ -656,6 +703,54 @@ var requestNoContent = async (configuration, dependencies, route, requestOptions
|
|
|
656
703
|
var getResolvedMetricsDateRange = (range) => range ?? getDefaultMetricsDateRange();
|
|
657
704
|
var getMetricsDateRangeQuery = (range) => `startDate=${encodeURIComponent(range.startDate)}&endDate=${encodeURIComponent(range.endDate)}`;
|
|
658
705
|
var getMetricsAsOfDateQuery = (asOfDate) => `asOfDate=${encodeURIComponent(asOfDate)}`;
|
|
706
|
+
var addUtcDays = (dateStr, days) => {
|
|
707
|
+
const d = /* @__PURE__ */ new Date(`${dateStr}T00:00:00Z`);
|
|
708
|
+
d.setUTCDate(d.getUTCDate() + days);
|
|
709
|
+
return d.toISOString().split("T")[0];
|
|
710
|
+
};
|
|
711
|
+
var computeItemAge = (dayDate, startedDate) => {
|
|
712
|
+
const day = Date.parse(`${dayDate}T00:00:00Z`);
|
|
713
|
+
const started = Date.parse(startedDate);
|
|
714
|
+
const diffDays = Math.floor((day - started) / 864e5);
|
|
715
|
+
return Math.max(1, diffDays + 1);
|
|
716
|
+
};
|
|
717
|
+
var deriveWorkItemAgeOverTime = (startDate, endDate, wipData) => {
|
|
718
|
+
const daily = Object.entries(
|
|
719
|
+
wipData.workItemsPerUnitOfTime
|
|
720
|
+
).map(([dayIndexStr, items]) => {
|
|
721
|
+
const dayIndex = Number.parseInt(dayIndexStr, 10);
|
|
722
|
+
const date = addUtcDays(startDate, dayIndex);
|
|
723
|
+
const ageItems = items.filter(
|
|
724
|
+
(item) => item.startedDate != null && item.startedDate.length > 0
|
|
725
|
+
).map((item) => ({
|
|
726
|
+
id: item.id,
|
|
727
|
+
name: item.name,
|
|
728
|
+
referenceId: item.referenceId,
|
|
729
|
+
age: computeItemAge(date, item.startedDate)
|
|
730
|
+
}));
|
|
731
|
+
return { date, items: ageItems };
|
|
732
|
+
});
|
|
733
|
+
daily.sort((a, b) => a.date.localeCompare(b.date));
|
|
734
|
+
return { startDate, endDate, daily };
|
|
735
|
+
};
|
|
736
|
+
var deriveTotalWorkItemAgeOverTime = (startDate, endDate, wipData) => {
|
|
737
|
+
const daily = Object.entries(
|
|
738
|
+
wipData.workItemsPerUnitOfTime
|
|
739
|
+
).map(([dayIndexStr, items]) => {
|
|
740
|
+
const dayIndex = Number.parseInt(dayIndexStr, 10);
|
|
741
|
+
const date = addUtcDays(startDate, dayIndex);
|
|
742
|
+
const activeItems = items.filter(
|
|
743
|
+
(item) => item.startedDate != null && item.startedDate.length > 0
|
|
744
|
+
);
|
|
745
|
+
const totalAge = activeItems.reduce(
|
|
746
|
+
(sum, item) => sum + computeItemAge(date, item.startedDate),
|
|
747
|
+
0
|
|
748
|
+
);
|
|
749
|
+
return { date, totalAge, itemCount: activeItems.length };
|
|
750
|
+
});
|
|
751
|
+
daily.sort((a, b) => a.date.localeCompare(b.date));
|
|
752
|
+
return { startDate, endDate, daily };
|
|
753
|
+
};
|
|
659
754
|
var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
660
755
|
checkConnectivity: async () => {
|
|
661
756
|
const fetchDependency = getFetchDependency(dependencies);
|
|
@@ -850,6 +945,42 @@ var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
|
850
945
|
{ method: "GET" }
|
|
851
946
|
);
|
|
852
947
|
},
|
|
948
|
+
getTeamWorkItemAgeOverTime: async (teamId, range) => {
|
|
949
|
+
const r = getResolvedMetricsDateRange(range);
|
|
950
|
+
const wipResult = await requestJson(
|
|
951
|
+
configuration,
|
|
952
|
+
dependencies,
|
|
953
|
+
`/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
954
|
+
{ method: "GET" }
|
|
955
|
+
);
|
|
956
|
+
if (!wipResult.ok) {
|
|
957
|
+
return wipResult;
|
|
958
|
+
}
|
|
959
|
+
return {
|
|
960
|
+
ok: true,
|
|
961
|
+
value: deriveWorkItemAgeOverTime(r.startDate, r.endDate, wipResult.value)
|
|
962
|
+
};
|
|
963
|
+
},
|
|
964
|
+
getTeamTotalWorkItemAgeOverTime: async (teamId, range) => {
|
|
965
|
+
const r = getResolvedMetricsDateRange(range);
|
|
966
|
+
const wipResult = await requestJson(
|
|
967
|
+
configuration,
|
|
968
|
+
dependencies,
|
|
969
|
+
`/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
970
|
+
{ method: "GET" }
|
|
971
|
+
);
|
|
972
|
+
if (!wipResult.ok) {
|
|
973
|
+
return wipResult;
|
|
974
|
+
}
|
|
975
|
+
return {
|
|
976
|
+
ok: true,
|
|
977
|
+
value: deriveTotalWorkItemAgeOverTime(
|
|
978
|
+
r.startDate,
|
|
979
|
+
r.endDate,
|
|
980
|
+
wipResult.value
|
|
981
|
+
)
|
|
982
|
+
};
|
|
983
|
+
},
|
|
853
984
|
getPortfolioThroughput: async (portfolioId, range) => {
|
|
854
985
|
const r = getResolvedMetricsDateRange(range);
|
|
855
986
|
return requestJson(
|
|
@@ -925,6 +1056,42 @@ var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
|
925
1056
|
{ method: "GET" }
|
|
926
1057
|
);
|
|
927
1058
|
},
|
|
1059
|
+
getPortfolioWorkItemAgeOverTime: async (portfolioId, range) => {
|
|
1060
|
+
const r = getResolvedMetricsDateRange(range);
|
|
1061
|
+
const wipResult = await requestJson(
|
|
1062
|
+
configuration,
|
|
1063
|
+
dependencies,
|
|
1064
|
+
`/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
1065
|
+
{ method: "GET" }
|
|
1066
|
+
);
|
|
1067
|
+
if (!wipResult.ok) {
|
|
1068
|
+
return wipResult;
|
|
1069
|
+
}
|
|
1070
|
+
return {
|
|
1071
|
+
ok: true,
|
|
1072
|
+
value: deriveWorkItemAgeOverTime(r.startDate, r.endDate, wipResult.value)
|
|
1073
|
+
};
|
|
1074
|
+
},
|
|
1075
|
+
getPortfolioTotalWorkItemAgeOverTime: async (portfolioId, range) => {
|
|
1076
|
+
const r = getResolvedMetricsDateRange(range);
|
|
1077
|
+
const wipResult = await requestJson(
|
|
1078
|
+
configuration,
|
|
1079
|
+
dependencies,
|
|
1080
|
+
`/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
1081
|
+
{ method: "GET" }
|
|
1082
|
+
);
|
|
1083
|
+
if (!wipResult.ok) {
|
|
1084
|
+
return wipResult;
|
|
1085
|
+
}
|
|
1086
|
+
return {
|
|
1087
|
+
ok: true,
|
|
1088
|
+
value: deriveTotalWorkItemAgeOverTime(
|
|
1089
|
+
r.startDate,
|
|
1090
|
+
r.endDate,
|
|
1091
|
+
wipResult.value
|
|
1092
|
+
)
|
|
1093
|
+
};
|
|
1094
|
+
},
|
|
928
1095
|
getFeaturesByIds: async (ids) => {
|
|
929
1096
|
const queryString = ids.map((id) => `ids=${encodeURIComponent(id)}`).join("&");
|
|
930
1097
|
return requestJson(
|
|
@@ -992,6 +1159,8 @@ var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
|
992
1159
|
createLighthouseClient,
|
|
993
1160
|
getClientPackageContract,
|
|
994
1161
|
getDefaultMetricsDateRange,
|
|
1162
|
+
getStandaloneDiscoveryLockfilePath,
|
|
1163
|
+
loadStandaloneDiscoveryContract,
|
|
995
1164
|
parseStandaloneDiscoveryContract,
|
|
996
1165
|
pollCliAuthSession,
|
|
997
1166
|
queryServerAuthMode,
|
package/dist/index.d.cts
CHANGED
|
@@ -50,6 +50,8 @@ type ConnectivityValidationResult = {
|
|
|
50
50
|
readonly endpoint?: ResolvedLighthouseEndpoint;
|
|
51
51
|
};
|
|
52
52
|
declare const parseStandaloneDiscoveryContract: (serializedContract: string) => StandaloneDiscoveryContractParseResult;
|
|
53
|
+
declare const getStandaloneDiscoveryLockfilePath: () => string;
|
|
54
|
+
declare const loadStandaloneDiscoveryContract: () => Promise<StandaloneDiscoveryContract | null>;
|
|
53
55
|
declare const validateLighthouseConnectivity: (configuration: LighthouseConnectionConfiguration, dependencies: ConnectivityDependencies, requestInit?: RequestInit) => Promise<ConnectivityValidationResult>;
|
|
54
56
|
type LighthouseClientAuth = {
|
|
55
57
|
readonly kind: "none";
|
|
@@ -167,6 +169,31 @@ type BacktestInput = {
|
|
|
167
169
|
readonly historicalStartDate: string;
|
|
168
170
|
readonly historicalEndDate: string;
|
|
169
171
|
};
|
|
172
|
+
type WorkItemAgeEntry = {
|
|
173
|
+
readonly id: number;
|
|
174
|
+
readonly name: string;
|
|
175
|
+
readonly referenceId: string;
|
|
176
|
+
readonly age: number;
|
|
177
|
+
};
|
|
178
|
+
type DailyWorkItemAge = {
|
|
179
|
+
readonly date: string;
|
|
180
|
+
readonly items: readonly WorkItemAgeEntry[];
|
|
181
|
+
};
|
|
182
|
+
type DailyTotalWorkItemAge = {
|
|
183
|
+
readonly date: string;
|
|
184
|
+
readonly totalAge: number;
|
|
185
|
+
readonly itemCount: number;
|
|
186
|
+
};
|
|
187
|
+
type WorkItemAgeOverTimeResult = {
|
|
188
|
+
readonly startDate: string;
|
|
189
|
+
readonly endDate: string;
|
|
190
|
+
readonly daily: readonly DailyWorkItemAge[];
|
|
191
|
+
};
|
|
192
|
+
type TotalWorkItemAgeOverTimeResult = {
|
|
193
|
+
readonly startDate: string;
|
|
194
|
+
readonly endDate: string;
|
|
195
|
+
readonly daily: readonly DailyTotalWorkItemAge[];
|
|
196
|
+
};
|
|
170
197
|
type LighthouseClient = {
|
|
171
198
|
readonly checkConnectivity: () => Promise<ConnectivityValidationResult>;
|
|
172
199
|
readonly getVersion: () => Promise<LighthouseApiResult<string>>;
|
|
@@ -203,8 +230,12 @@ type LighthouseClient = {
|
|
|
203
230
|
readonly getPortfolioWip: (portfolioId: number, asOfDate: string) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
204
231
|
readonly getPortfolioCycleTimeData: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
205
232
|
readonly getPortfolioPredictabilityScore: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<unknown>>;
|
|
233
|
+
readonly getTeamWorkItemAgeOverTime: (teamId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<WorkItemAgeOverTimeResult>>;
|
|
234
|
+
readonly getTeamTotalWorkItemAgeOverTime: (teamId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<TotalWorkItemAgeOverTimeResult>>;
|
|
206
235
|
readonly getPortfolioTotalWorkItemAge: (portfolioId: number, asOfDate: string) => Promise<LighthouseApiResult<number>>;
|
|
207
236
|
readonly getPortfolioTotalWorkItemAgeInfo: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<unknown>>;
|
|
237
|
+
readonly getPortfolioWorkItemAgeOverTime: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<WorkItemAgeOverTimeResult>>;
|
|
238
|
+
readonly getPortfolioTotalWorkItemAgeOverTime: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<TotalWorkItemAgeOverTimeResult>>;
|
|
208
239
|
readonly getFeaturesByIds: (ids: readonly number[]) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
209
240
|
readonly getFeaturesByReferences: (refs: readonly string[]) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
210
241
|
readonly getFeatureWorkItems: (featureId: number) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
@@ -220,4 +251,4 @@ type LighthouseClientDependencies = {
|
|
|
220
251
|
};
|
|
221
252
|
declare const createLighthouseClient: (configuration: LighthouseClientConfiguration, dependencies?: LighthouseClientDependencies) => LighthouseClient;
|
|
222
253
|
|
|
223
|
-
export { type BacktestInput, type CliAuthSessionPollResult, type CliAuthSessionStartError, type CliAuthSessionStartOutcome, type CliAuthSessionStartResult, type CliConnection, type CliServerAuthMode, type CliServerConnection, type CliStandaloneConnection, type ClientCapability, type ClientPackageContract, type ConnectivityCategory, type ConnectivityDependencies, type ConnectivityFetchResponse, type ConnectivityValidationResult, type LighthouseApiError, type LighthouseApiResult, type LighthouseAuthContext, type LighthouseAuthOverrides, type LighthouseAuthStatus, type LighthouseAuthStore, type LighthouseClient, type LighthouseClientAuth, type LighthouseClientConfiguration, type LighthouseClientDependencies, type LighthouseConnectionConfiguration, type LighthouseWritePayload, type ManualForecastInput, type MetricsDateRange, type ResolvedLighthouseEndpoint, type ServerAuthModeResult, type StandaloneDiscoveryContract, type StandaloneDiscoveryContractParseResult, type StoredLighthouseAuth, createLighthouseAuthContext, createLighthouseClient, getClientPackageContract, getDefaultMetricsDateRange, parseStandaloneDiscoveryContract, pollCliAuthSession, queryServerAuthMode, startCliAuthSession, validateLighthouseConnectivity };
|
|
254
|
+
export { type BacktestInput, type CliAuthSessionPollResult, type CliAuthSessionStartError, type CliAuthSessionStartOutcome, type CliAuthSessionStartResult, type CliConnection, type CliServerAuthMode, type CliServerConnection, type CliStandaloneConnection, type ClientCapability, type ClientPackageContract, type ConnectivityCategory, type ConnectivityDependencies, type ConnectivityFetchResponse, type ConnectivityValidationResult, type DailyTotalWorkItemAge, type DailyWorkItemAge, type LighthouseApiError, type LighthouseApiResult, type LighthouseAuthContext, type LighthouseAuthOverrides, type LighthouseAuthStatus, type LighthouseAuthStore, type LighthouseClient, type LighthouseClientAuth, type LighthouseClientConfiguration, type LighthouseClientDependencies, type LighthouseConnectionConfiguration, type LighthouseWritePayload, type ManualForecastInput, type MetricsDateRange, type ResolvedLighthouseEndpoint, type ServerAuthModeResult, type StandaloneDiscoveryContract, type StandaloneDiscoveryContractParseResult, type StoredLighthouseAuth, type TotalWorkItemAgeOverTimeResult, type WorkItemAgeEntry, type WorkItemAgeOverTimeResult, createLighthouseAuthContext, createLighthouseClient, getClientPackageContract, getDefaultMetricsDateRange, getStandaloneDiscoveryLockfilePath, loadStandaloneDiscoveryContract, parseStandaloneDiscoveryContract, pollCliAuthSession, queryServerAuthMode, startCliAuthSession, validateLighthouseConnectivity };
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ type ConnectivityValidationResult = {
|
|
|
50
50
|
readonly endpoint?: ResolvedLighthouseEndpoint;
|
|
51
51
|
};
|
|
52
52
|
declare const parseStandaloneDiscoveryContract: (serializedContract: string) => StandaloneDiscoveryContractParseResult;
|
|
53
|
+
declare const getStandaloneDiscoveryLockfilePath: () => string;
|
|
54
|
+
declare const loadStandaloneDiscoveryContract: () => Promise<StandaloneDiscoveryContract | null>;
|
|
53
55
|
declare const validateLighthouseConnectivity: (configuration: LighthouseConnectionConfiguration, dependencies: ConnectivityDependencies, requestInit?: RequestInit) => Promise<ConnectivityValidationResult>;
|
|
54
56
|
type LighthouseClientAuth = {
|
|
55
57
|
readonly kind: "none";
|
|
@@ -167,6 +169,31 @@ type BacktestInput = {
|
|
|
167
169
|
readonly historicalStartDate: string;
|
|
168
170
|
readonly historicalEndDate: string;
|
|
169
171
|
};
|
|
172
|
+
type WorkItemAgeEntry = {
|
|
173
|
+
readonly id: number;
|
|
174
|
+
readonly name: string;
|
|
175
|
+
readonly referenceId: string;
|
|
176
|
+
readonly age: number;
|
|
177
|
+
};
|
|
178
|
+
type DailyWorkItemAge = {
|
|
179
|
+
readonly date: string;
|
|
180
|
+
readonly items: readonly WorkItemAgeEntry[];
|
|
181
|
+
};
|
|
182
|
+
type DailyTotalWorkItemAge = {
|
|
183
|
+
readonly date: string;
|
|
184
|
+
readonly totalAge: number;
|
|
185
|
+
readonly itemCount: number;
|
|
186
|
+
};
|
|
187
|
+
type WorkItemAgeOverTimeResult = {
|
|
188
|
+
readonly startDate: string;
|
|
189
|
+
readonly endDate: string;
|
|
190
|
+
readonly daily: readonly DailyWorkItemAge[];
|
|
191
|
+
};
|
|
192
|
+
type TotalWorkItemAgeOverTimeResult = {
|
|
193
|
+
readonly startDate: string;
|
|
194
|
+
readonly endDate: string;
|
|
195
|
+
readonly daily: readonly DailyTotalWorkItemAge[];
|
|
196
|
+
};
|
|
170
197
|
type LighthouseClient = {
|
|
171
198
|
readonly checkConnectivity: () => Promise<ConnectivityValidationResult>;
|
|
172
199
|
readonly getVersion: () => Promise<LighthouseApiResult<string>>;
|
|
@@ -203,8 +230,12 @@ type LighthouseClient = {
|
|
|
203
230
|
readonly getPortfolioWip: (portfolioId: number, asOfDate: string) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
204
231
|
readonly getPortfolioCycleTimeData: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
205
232
|
readonly getPortfolioPredictabilityScore: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<unknown>>;
|
|
233
|
+
readonly getTeamWorkItemAgeOverTime: (teamId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<WorkItemAgeOverTimeResult>>;
|
|
234
|
+
readonly getTeamTotalWorkItemAgeOverTime: (teamId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<TotalWorkItemAgeOverTimeResult>>;
|
|
206
235
|
readonly getPortfolioTotalWorkItemAge: (portfolioId: number, asOfDate: string) => Promise<LighthouseApiResult<number>>;
|
|
207
236
|
readonly getPortfolioTotalWorkItemAgeInfo: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<unknown>>;
|
|
237
|
+
readonly getPortfolioWorkItemAgeOverTime: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<WorkItemAgeOverTimeResult>>;
|
|
238
|
+
readonly getPortfolioTotalWorkItemAgeOverTime: (portfolioId: number, range?: MetricsDateRange) => Promise<LighthouseApiResult<TotalWorkItemAgeOverTimeResult>>;
|
|
208
239
|
readonly getFeaturesByIds: (ids: readonly number[]) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
209
240
|
readonly getFeaturesByReferences: (refs: readonly string[]) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
210
241
|
readonly getFeatureWorkItems: (featureId: number) => Promise<LighthouseApiResult<readonly unknown[]>>;
|
|
@@ -220,4 +251,4 @@ type LighthouseClientDependencies = {
|
|
|
220
251
|
};
|
|
221
252
|
declare const createLighthouseClient: (configuration: LighthouseClientConfiguration, dependencies?: LighthouseClientDependencies) => LighthouseClient;
|
|
222
253
|
|
|
223
|
-
export { type BacktestInput, type CliAuthSessionPollResult, type CliAuthSessionStartError, type CliAuthSessionStartOutcome, type CliAuthSessionStartResult, type CliConnection, type CliServerAuthMode, type CliServerConnection, type CliStandaloneConnection, type ClientCapability, type ClientPackageContract, type ConnectivityCategory, type ConnectivityDependencies, type ConnectivityFetchResponse, type ConnectivityValidationResult, type LighthouseApiError, type LighthouseApiResult, type LighthouseAuthContext, type LighthouseAuthOverrides, type LighthouseAuthStatus, type LighthouseAuthStore, type LighthouseClient, type LighthouseClientAuth, type LighthouseClientConfiguration, type LighthouseClientDependencies, type LighthouseConnectionConfiguration, type LighthouseWritePayload, type ManualForecastInput, type MetricsDateRange, type ResolvedLighthouseEndpoint, type ServerAuthModeResult, type StandaloneDiscoveryContract, type StandaloneDiscoveryContractParseResult, type StoredLighthouseAuth, createLighthouseAuthContext, createLighthouseClient, getClientPackageContract, getDefaultMetricsDateRange, parseStandaloneDiscoveryContract, pollCliAuthSession, queryServerAuthMode, startCliAuthSession, validateLighthouseConnectivity };
|
|
254
|
+
export { type BacktestInput, type CliAuthSessionPollResult, type CliAuthSessionStartError, type CliAuthSessionStartOutcome, type CliAuthSessionStartResult, type CliConnection, type CliServerAuthMode, type CliServerConnection, type CliStandaloneConnection, type ClientCapability, type ClientPackageContract, type ConnectivityCategory, type ConnectivityDependencies, type ConnectivityFetchResponse, type ConnectivityValidationResult, type DailyTotalWorkItemAge, type DailyWorkItemAge, type LighthouseApiError, type LighthouseApiResult, type LighthouseAuthContext, type LighthouseAuthOverrides, type LighthouseAuthStatus, type LighthouseAuthStore, type LighthouseClient, type LighthouseClientAuth, type LighthouseClientConfiguration, type LighthouseClientDependencies, type LighthouseConnectionConfiguration, type LighthouseWritePayload, type ManualForecastInput, type MetricsDateRange, type ResolvedLighthouseEndpoint, type ServerAuthModeResult, type StandaloneDiscoveryContract, type StandaloneDiscoveryContractParseResult, type StoredLighthouseAuth, type TotalWorkItemAgeOverTimeResult, type WorkItemAgeEntry, type WorkItemAgeOverTimeResult, createLighthouseAuthContext, createLighthouseClient, getClientPackageContract, getDefaultMetricsDateRange, getStandaloneDiscoveryLockfilePath, loadStandaloneDiscoveryContract, parseStandaloneDiscoveryContract, pollCliAuthSession, queryServerAuthMode, startCliAuthSession, validateLighthouseConnectivity };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
2
5
|
var getClientPackageContract = () => ({
|
|
3
6
|
name: "@letpeoplework/lighthouse-client",
|
|
4
7
|
capabilities: [
|
|
@@ -9,6 +12,7 @@ var getClientPackageContract = () => ({
|
|
|
9
12
|
]
|
|
10
13
|
});
|
|
11
14
|
var SUPPORTED_DISCOVERY_CONTRACT_VERSION = 1;
|
|
15
|
+
var STANDALONE_DISCOVERY_LOCKFILE_NAME = "standalone.lock.json";
|
|
12
16
|
var isObjectRecord = (value) => {
|
|
13
17
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
18
|
};
|
|
@@ -123,6 +127,47 @@ var parseStandaloneDiscoveryContract = (serializedContract) => {
|
|
|
123
127
|
detectedAtUtc
|
|
124
128
|
});
|
|
125
129
|
};
|
|
130
|
+
var getStandaloneDiscoveryLockfilePath = () => {
|
|
131
|
+
if (process.env.LIGHTHOUSE_STANDALONE_LOCKFILE_PATH !== void 0) {
|
|
132
|
+
return process.env.LIGHTHOUSE_STANDALONE_LOCKFILE_PATH;
|
|
133
|
+
}
|
|
134
|
+
if (process.platform === "darwin") {
|
|
135
|
+
return join(
|
|
136
|
+
homedir(),
|
|
137
|
+
"Library",
|
|
138
|
+
"Application Support",
|
|
139
|
+
"Lighthouse",
|
|
140
|
+
STANDALONE_DISCOVERY_LOCKFILE_NAME
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
if (process.platform === "win32") {
|
|
144
|
+
return join(
|
|
145
|
+
process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"),
|
|
146
|
+
"Lighthouse",
|
|
147
|
+
STANDALONE_DISCOVERY_LOCKFILE_NAME
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return join(
|
|
151
|
+
process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"),
|
|
152
|
+
"Lighthouse",
|
|
153
|
+
STANDALONE_DISCOVERY_LOCKFILE_NAME
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
var loadStandaloneDiscoveryContract = async () => {
|
|
157
|
+
try {
|
|
158
|
+
const serializedContract = await readFile(
|
|
159
|
+
getStandaloneDiscoveryLockfilePath(),
|
|
160
|
+
"utf8"
|
|
161
|
+
);
|
|
162
|
+
const parsedContract = parseStandaloneDiscoveryContract(serializedContract);
|
|
163
|
+
if (!parsedContract.isValid) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return parsedContract.contract;
|
|
167
|
+
} catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
126
171
|
var getResolvedEndpoint = (mode, lighthouseUrl) => {
|
|
127
172
|
const apiBaseUrl = getApiBaseUrl(lighthouseUrl);
|
|
128
173
|
return {
|
|
@@ -624,6 +669,54 @@ var requestNoContent = async (configuration, dependencies, route, requestOptions
|
|
|
624
669
|
var getResolvedMetricsDateRange = (range) => range ?? getDefaultMetricsDateRange();
|
|
625
670
|
var getMetricsDateRangeQuery = (range) => `startDate=${encodeURIComponent(range.startDate)}&endDate=${encodeURIComponent(range.endDate)}`;
|
|
626
671
|
var getMetricsAsOfDateQuery = (asOfDate) => `asOfDate=${encodeURIComponent(asOfDate)}`;
|
|
672
|
+
var addUtcDays = (dateStr, days) => {
|
|
673
|
+
const d = /* @__PURE__ */ new Date(`${dateStr}T00:00:00Z`);
|
|
674
|
+
d.setUTCDate(d.getUTCDate() + days);
|
|
675
|
+
return d.toISOString().split("T")[0];
|
|
676
|
+
};
|
|
677
|
+
var computeItemAge = (dayDate, startedDate) => {
|
|
678
|
+
const day = Date.parse(`${dayDate}T00:00:00Z`);
|
|
679
|
+
const started = Date.parse(startedDate);
|
|
680
|
+
const diffDays = Math.floor((day - started) / 864e5);
|
|
681
|
+
return Math.max(1, diffDays + 1);
|
|
682
|
+
};
|
|
683
|
+
var deriveWorkItemAgeOverTime = (startDate, endDate, wipData) => {
|
|
684
|
+
const daily = Object.entries(
|
|
685
|
+
wipData.workItemsPerUnitOfTime
|
|
686
|
+
).map(([dayIndexStr, items]) => {
|
|
687
|
+
const dayIndex = Number.parseInt(dayIndexStr, 10);
|
|
688
|
+
const date = addUtcDays(startDate, dayIndex);
|
|
689
|
+
const ageItems = items.filter(
|
|
690
|
+
(item) => item.startedDate != null && item.startedDate.length > 0
|
|
691
|
+
).map((item) => ({
|
|
692
|
+
id: item.id,
|
|
693
|
+
name: item.name,
|
|
694
|
+
referenceId: item.referenceId,
|
|
695
|
+
age: computeItemAge(date, item.startedDate)
|
|
696
|
+
}));
|
|
697
|
+
return { date, items: ageItems };
|
|
698
|
+
});
|
|
699
|
+
daily.sort((a, b) => a.date.localeCompare(b.date));
|
|
700
|
+
return { startDate, endDate, daily };
|
|
701
|
+
};
|
|
702
|
+
var deriveTotalWorkItemAgeOverTime = (startDate, endDate, wipData) => {
|
|
703
|
+
const daily = Object.entries(
|
|
704
|
+
wipData.workItemsPerUnitOfTime
|
|
705
|
+
).map(([dayIndexStr, items]) => {
|
|
706
|
+
const dayIndex = Number.parseInt(dayIndexStr, 10);
|
|
707
|
+
const date = addUtcDays(startDate, dayIndex);
|
|
708
|
+
const activeItems = items.filter(
|
|
709
|
+
(item) => item.startedDate != null && item.startedDate.length > 0
|
|
710
|
+
);
|
|
711
|
+
const totalAge = activeItems.reduce(
|
|
712
|
+
(sum, item) => sum + computeItemAge(date, item.startedDate),
|
|
713
|
+
0
|
|
714
|
+
);
|
|
715
|
+
return { date, totalAge, itemCount: activeItems.length };
|
|
716
|
+
});
|
|
717
|
+
daily.sort((a, b) => a.date.localeCompare(b.date));
|
|
718
|
+
return { startDate, endDate, daily };
|
|
719
|
+
};
|
|
627
720
|
var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
628
721
|
checkConnectivity: async () => {
|
|
629
722
|
const fetchDependency = getFetchDependency(dependencies);
|
|
@@ -818,6 +911,42 @@ var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
|
818
911
|
{ method: "GET" }
|
|
819
912
|
);
|
|
820
913
|
},
|
|
914
|
+
getTeamWorkItemAgeOverTime: async (teamId, range) => {
|
|
915
|
+
const r = getResolvedMetricsDateRange(range);
|
|
916
|
+
const wipResult = await requestJson(
|
|
917
|
+
configuration,
|
|
918
|
+
dependencies,
|
|
919
|
+
`/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
920
|
+
{ method: "GET" }
|
|
921
|
+
);
|
|
922
|
+
if (!wipResult.ok) {
|
|
923
|
+
return wipResult;
|
|
924
|
+
}
|
|
925
|
+
return {
|
|
926
|
+
ok: true,
|
|
927
|
+
value: deriveWorkItemAgeOverTime(r.startDate, r.endDate, wipResult.value)
|
|
928
|
+
};
|
|
929
|
+
},
|
|
930
|
+
getTeamTotalWorkItemAgeOverTime: async (teamId, range) => {
|
|
931
|
+
const r = getResolvedMetricsDateRange(range);
|
|
932
|
+
const wipResult = await requestJson(
|
|
933
|
+
configuration,
|
|
934
|
+
dependencies,
|
|
935
|
+
`/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
936
|
+
{ method: "GET" }
|
|
937
|
+
);
|
|
938
|
+
if (!wipResult.ok) {
|
|
939
|
+
return wipResult;
|
|
940
|
+
}
|
|
941
|
+
return {
|
|
942
|
+
ok: true,
|
|
943
|
+
value: deriveTotalWorkItemAgeOverTime(
|
|
944
|
+
r.startDate,
|
|
945
|
+
r.endDate,
|
|
946
|
+
wipResult.value
|
|
947
|
+
)
|
|
948
|
+
};
|
|
949
|
+
},
|
|
821
950
|
getPortfolioThroughput: async (portfolioId, range) => {
|
|
822
951
|
const r = getResolvedMetricsDateRange(range);
|
|
823
952
|
return requestJson(
|
|
@@ -893,6 +1022,42 @@ var createLighthouseClient = (configuration, dependencies = {}) => ({
|
|
|
893
1022
|
{ method: "GET" }
|
|
894
1023
|
);
|
|
895
1024
|
},
|
|
1025
|
+
getPortfolioWorkItemAgeOverTime: async (portfolioId, range) => {
|
|
1026
|
+
const r = getResolvedMetricsDateRange(range);
|
|
1027
|
+
const wipResult = await requestJson(
|
|
1028
|
+
configuration,
|
|
1029
|
+
dependencies,
|
|
1030
|
+
`/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
1031
|
+
{ method: "GET" }
|
|
1032
|
+
);
|
|
1033
|
+
if (!wipResult.ok) {
|
|
1034
|
+
return wipResult;
|
|
1035
|
+
}
|
|
1036
|
+
return {
|
|
1037
|
+
ok: true,
|
|
1038
|
+
value: deriveWorkItemAgeOverTime(r.startDate, r.endDate, wipResult.value)
|
|
1039
|
+
};
|
|
1040
|
+
},
|
|
1041
|
+
getPortfolioTotalWorkItemAgeOverTime: async (portfolioId, range) => {
|
|
1042
|
+
const r = getResolvedMetricsDateRange(range);
|
|
1043
|
+
const wipResult = await requestJson(
|
|
1044
|
+
configuration,
|
|
1045
|
+
dependencies,
|
|
1046
|
+
`/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
|
|
1047
|
+
{ method: "GET" }
|
|
1048
|
+
);
|
|
1049
|
+
if (!wipResult.ok) {
|
|
1050
|
+
return wipResult;
|
|
1051
|
+
}
|
|
1052
|
+
return {
|
|
1053
|
+
ok: true,
|
|
1054
|
+
value: deriveTotalWorkItemAgeOverTime(
|
|
1055
|
+
r.startDate,
|
|
1056
|
+
r.endDate,
|
|
1057
|
+
wipResult.value
|
|
1058
|
+
)
|
|
1059
|
+
};
|
|
1060
|
+
},
|
|
896
1061
|
getFeaturesByIds: async (ids) => {
|
|
897
1062
|
const queryString = ids.map((id) => `ids=${encodeURIComponent(id)}`).join("&");
|
|
898
1063
|
return requestJson(
|
|
@@ -959,6 +1124,8 @@ export {
|
|
|
959
1124
|
createLighthouseClient,
|
|
960
1125
|
getClientPackageContract,
|
|
961
1126
|
getDefaultMetricsDateRange,
|
|
1127
|
+
getStandaloneDiscoveryLockfilePath,
|
|
1128
|
+
loadStandaloneDiscoveryContract,
|
|
962
1129
|
parseStandaloneDiscoveryContract,
|
|
963
1130
|
pollCliAuthSession,
|
|
964
1131
|
queryServerAuthMode,
|
package/package.json
CHANGED