@letpeoplework/lighthouse-client 1.1.0 → 1.3.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
@@ -544,6 +544,47 @@ var toApiError = (statusCode, reason) => ({
544
544
  reason,
545
545
  statusCode
546
546
  });
547
+ var CONCURRENCY_CONFLICT_STATUS = 409;
548
+ var CONCURRENCY_CONFLICT_GUIDANCE = "This edit conflicts because the item was changed by someone else. Re-fetch the current settings to obtain the latest concurrency token, then re-apply your change.";
549
+ var getProblemDetailsMessage = (body) => {
550
+ if (!isObjectRecord(body)) {
551
+ return void 0;
552
+ }
553
+ for (const key of ["detail", "title", "message"]) {
554
+ const value = body[key];
555
+ if (typeof value === "string" && value.trim().length > 0) {
556
+ return value.trim();
557
+ }
558
+ }
559
+ return void 0;
560
+ };
561
+ var getResponseBody = async (response) => {
562
+ try {
563
+ if (response.json !== void 0) {
564
+ return await response.json();
565
+ }
566
+ return JSON.parse(await response.text());
567
+ } catch {
568
+ return void 0;
569
+ }
570
+ };
571
+ var toConcurrencyConflictError = (serverMessage) => ({
572
+ category: "concurrency-conflict",
573
+ reason: serverMessage === void 0 ? CONCURRENCY_CONFLICT_GUIDANCE : `${serverMessage} ${CONCURRENCY_CONFLICT_GUIDANCE}`,
574
+ statusCode: CONCURRENCY_CONFLICT_STATUS
575
+ });
576
+ var toResponseError = async (response) => {
577
+ if (response.status === CONCURRENCY_CONFLICT_STATUS) {
578
+ const serverMessage = getProblemDetailsMessage(
579
+ await getResponseBody(response)
580
+ );
581
+ return toConcurrencyConflictError(serverMessage);
582
+ }
583
+ return toApiError(
584
+ response.status,
585
+ `Request failed with status ${response.status}.`
586
+ );
587
+ };
547
588
  var requestText = async (configuration, dependencies, route) => {
548
589
  const fetchDependency = getFetchDependency(dependencies);
549
590
  const connectivityResult = await validateLighthouseConnectivity(
@@ -562,12 +603,7 @@ var requestText = async (configuration, dependencies, route) => {
562
603
  getRequestInit(configuration.auth)
563
604
  );
564
605
  if (!response.ok) {
565
- return getErrorResult(
566
- toApiError(
567
- response.status,
568
- `Request failed with status ${response.status}.`
569
- )
570
- );
606
+ return getErrorResult(await toResponseError(response));
571
607
  }
572
608
  return {
573
609
  ok: true,
@@ -601,12 +637,7 @@ var requestJson = async (configuration, dependencies, route, requestOptions) =>
601
637
  getRequestInit(configuration.auth, requestOptions)
602
638
  );
603
639
  if (!response.ok) {
604
- return getErrorResult(
605
- toApiError(
606
- response.status,
607
- `Request failed with status ${response.status}.`
608
- )
609
- );
640
+ return getErrorResult(await toResponseError(response));
610
641
  }
611
642
  if (response.json === void 0) {
612
643
  return {
@@ -647,12 +678,7 @@ var requestNoContent = async (configuration, dependencies, route, requestOptions
647
678
  getRequestInit(configuration.auth, requestOptions)
648
679
  );
649
680
  if (!response.ok) {
650
- return getErrorResult(
651
- toApiError(
652
- response.status,
653
- `Request failed with status ${response.status}.`
654
- )
655
- );
681
+ return getErrorResult(await toResponseError(response));
656
682
  }
657
683
  return {
658
684
  ok: true,
@@ -669,6 +695,7 @@ var requestNoContent = async (configuration, dependencies, route, requestOptions
669
695
  var getResolvedMetricsDateRange = (range) => range ?? getDefaultMetricsDateRange();
670
696
  var getMetricsDateRangeQuery = (range) => `startDate=${encodeURIComponent(range.startDate)}&endDate=${encodeURIComponent(range.endDate)}`;
671
697
  var getMetricsAsOfDateQuery = (asOfDate) => `asOfDate=${encodeURIComponent(asOfDate)}`;
698
+ var getItemIdsQuerySuffix = (itemIds) => itemIds && itemIds.length > 0 ? itemIds.map((id) => `&itemIds=${encodeURIComponent(id)}`).join("") : "";
672
699
  var getViewQuerySuffix = (view) => view === "filtered" ? "&view=filtered" : "";
673
700
  var addUtcDays = (dateStr, days) => {
674
701
  const d = /* @__PURE__ */ new Date(`${dateStr}T00:00:00Z`);
@@ -719,414 +746,621 @@ var deriveTotalWorkItemAgeOverTime = (startDate, endDate, wipData) => {
719
746
  daily.sort((a, b) => a.date.localeCompare(b.date));
720
747
  return { startDate, endDate, daily };
721
748
  };
722
- var createLighthouseClient = (configuration, dependencies = {}) => ({
723
- checkConnectivity: async () => {
724
- const fetchDependency = getFetchDependency(dependencies);
725
- return validateLighthouseConnectivity(
726
- configuration.connection,
727
- {
728
- fetch: fetchDependency
729
- },
730
- getRequestInit(configuration.auth)
731
- );
732
- },
733
- getVersion: async () => requestText(configuration, dependencies, "/v1/version/current"),
734
- listWorkTrackingConnections: async () => requestJson(
735
- configuration,
736
- dependencies,
737
- "/v1/worktrackingsystemconnections",
738
- {
739
- method: "GET"
740
- }
741
- ),
742
- getWorkTrackingConnection: async (connectionId) => requestJson(
743
- configuration,
744
- dependencies,
745
- `/v1/worktrackingsystemconnections/${connectionId}`,
746
- {
747
- method: "GET"
748
- }
749
- ),
750
- createWorkTrackingConnection: async (payload) => requestJson(
751
- configuration,
752
- dependencies,
753
- "/v1/worktrackingsystemconnections",
754
- {
755
- method: "POST",
756
- body: payload
757
- }
758
- ),
759
- updateWorkTrackingConnection: async (connectionId, payload) => requestJson(
760
- configuration,
761
- dependencies,
762
- `/v1/worktrackingsystemconnections/${connectionId}`,
763
- {
764
- method: "PUT",
765
- body: payload
766
- }
767
- ),
768
- deleteWorkTrackingConnection: async (connectionId) => requestNoContent(
769
- configuration,
770
- dependencies,
771
- `/v1/worktrackingsystemconnections/${connectionId}`,
772
- {
773
- method: "DELETE"
774
- }
775
- ),
776
- listTeams: async () => requestJson(configuration, dependencies, "/v1/teams", {
777
- method: "GET"
778
- }),
779
- getTeam: async (teamId) => requestJson(configuration, dependencies, `/v1/teams/${teamId}`, {
780
- method: "GET"
781
- }),
782
- createTeam: async (payload) => requestJson(configuration, dependencies, "/v1/teams", {
783
- method: "POST",
784
- body: payload
785
- }),
786
- updateTeam: async (teamId, payload) => requestJson(configuration, dependencies, `/v1/teams/${teamId}`, {
787
- method: "PUT",
788
- body: payload
789
- }),
790
- deleteTeam: async (teamId) => requestNoContent(configuration, dependencies, `/v1/teams/${teamId}`, {
791
- method: "DELETE"
792
- }),
793
- refreshTeam: async (teamId) => requestNoContent(configuration, dependencies, `/v1/teams/${teamId}`, {
794
- method: "POST"
795
- }),
796
- listPortfolios: async () => requestJson(
797
- configuration,
798
- dependencies,
799
- "/v1/portfolios",
800
- {
801
- method: "GET"
749
+ var FEATURE_REQUIRES_SERVER_NEWER_THAN = {
750
+ cumulativeStateTime: "v26.5.24.10",
751
+ recurringBlackoutRules: "v26.5.29.5"
752
+ };
753
+ var parseServerVersion = (raw) => {
754
+ const trimmed = raw.trim().replace(/^v/iu, "");
755
+ if (trimmed.length === 0) {
756
+ return null;
757
+ }
758
+ const segments = trimmed.split(".");
759
+ const parsed = [];
760
+ for (const segment of segments) {
761
+ if (!/^\d+$/u.test(segment)) {
762
+ return null;
802
763
  }
803
- ),
804
- getPortfolio: async (portfolioId) => requestJson(
805
- configuration,
806
- dependencies,
807
- `/v1/portfolios/${portfolioId}`,
808
- {
809
- method: "GET"
764
+ parsed.push(Number(segment));
765
+ }
766
+ return parsed.length > 0 ? parsed : null;
767
+ };
768
+ var isServerVersionNewerThan = (candidate, baseline) => {
769
+ const left = parseServerVersion(candidate);
770
+ const right = parseServerVersion(baseline);
771
+ if (left === null || right === null) {
772
+ return null;
773
+ }
774
+ const length = Math.max(left.length, right.length);
775
+ for (let index = 0; index < length; index += 1) {
776
+ const l = left[index] ?? 0;
777
+ const r = right[index] ?? 0;
778
+ if (l !== r) {
779
+ return l > r;
810
780
  }
811
- ),
812
- createPortfolio: async (payload) => requestJson(configuration, dependencies, "/v1/portfolios", {
813
- method: "POST",
814
- body: payload
815
- }),
816
- updatePortfolio: async (portfolioId, payload) => requestJson(
817
- configuration,
818
- dependencies,
819
- `/v1/portfolios/${portfolioId}`,
820
- {
821
- method: "PUT",
822
- body: payload
781
+ }
782
+ return false;
783
+ };
784
+ var createLighthouseClient = (configuration, dependencies = {}) => {
785
+ let cachedServerVersion;
786
+ const getCachedServerVersion = async () => {
787
+ if (cachedServerVersion === void 0) {
788
+ const result = await requestText(
789
+ configuration,
790
+ dependencies,
791
+ "/v1/version/current"
792
+ );
793
+ cachedServerVersion = result.ok ? result.value : null;
823
794
  }
824
- ),
825
- deletePortfolio: async (portfolioId) => requestNoContent(
826
- configuration,
827
- dependencies,
828
- `/v1/portfolios/${portfolioId}`,
829
- {
830
- method: "DELETE"
795
+ return cachedServerVersion;
796
+ };
797
+ const ensureServerSupports = async (feature) => {
798
+ const version = await getCachedServerVersion();
799
+ if (version === null) {
800
+ return null;
831
801
  }
832
- ),
833
- refreshPortfolio: async (portfolioId) => requestNoContent(
834
- configuration,
835
- dependencies,
836
- `/v1/portfolios/${portfolioId}/refresh`,
837
- {
838
- method: "POST"
802
+ const baseline = FEATURE_REQUIRES_SERVER_NEWER_THAN[feature];
803
+ const newer = isServerVersionNewerThan(version, baseline);
804
+ if (newer === null || newer) {
805
+ return null;
839
806
  }
840
- ),
841
- getTeamThroughput: async (teamId, range, view) => {
842
- const r = getResolvedMetricsDateRange(range);
843
- return requestJson(
807
+ return {
808
+ ok: false,
809
+ error: {
810
+ category: "misconfigured",
811
+ reason: `This Lighthouse server (${version}) does not support "${feature}" \u2014 it requires a version newer than ${baseline}. Upgrade Lighthouse to use this client feature.`
812
+ }
813
+ };
814
+ };
815
+ return {
816
+ checkConnectivity: async () => {
817
+ const fetchDependency = getFetchDependency(dependencies);
818
+ return validateLighthouseConnectivity(
819
+ configuration.connection,
820
+ {
821
+ fetch: fetchDependency
822
+ },
823
+ getRequestInit(configuration.auth)
824
+ );
825
+ },
826
+ getVersion: async () => requestText(configuration, dependencies, "/v1/version/current"),
827
+ listWorkTrackingConnections: async () => requestJson(
844
828
  configuration,
845
829
  dependencies,
846
- `/v1/teams/${teamId}/metrics/throughput?${getMetricsDateRangeQuery(r)}${getViewQuerySuffix(view)}`,
847
- { method: "GET" }
848
- );
849
- },
850
- getTeamArrivals: async (teamId, range) => {
851
- const r = getResolvedMetricsDateRange(range);
852
- return requestJson(
830
+ "/v1/worktrackingsystemconnections",
831
+ {
832
+ method: "GET"
833
+ }
834
+ ),
835
+ getWorkTrackingConnection: async (connectionId) => requestJson(
853
836
  configuration,
854
837
  dependencies,
855
- `/v1/teams/${teamId}/metrics/arrivals?${getMetricsDateRangeQuery(r)}`,
856
- { method: "GET" }
857
- );
858
- },
859
- getTeamWipOverTime: async (teamId, range) => {
860
- const r = getResolvedMetricsDateRange(range);
861
- return requestJson(
838
+ `/v1/worktrackingsystemconnections/${connectionId}`,
839
+ {
840
+ method: "GET"
841
+ }
842
+ ),
843
+ createWorkTrackingConnection: async (payload) => requestJson(
862
844
  configuration,
863
845
  dependencies,
864
- `/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
865
- { method: "GET" }
866
- );
867
- },
868
- getTeamWip: async (teamId, asOfDate) => requestJson(
869
- configuration,
870
- dependencies,
871
- `/v1/teams/${teamId}/metrics/wip?${getMetricsAsOfDateQuery(asOfDate)}`,
872
- { method: "GET" }
873
- ),
874
- getTeamCycleTimePercentiles: async (teamId, range) => {
875
- const r = getResolvedMetricsDateRange(range);
876
- return requestJson(
846
+ "/v1/worktrackingsystemconnections",
847
+ {
848
+ method: "POST",
849
+ body: payload
850
+ }
851
+ ),
852
+ updateWorkTrackingConnection: async (connectionId, payload) => requestJson(
877
853
  configuration,
878
854
  dependencies,
879
- `/v1/teams/${teamId}/metrics/cycleTimePercentiles?${getMetricsDateRangeQuery(r)}`,
880
- { method: "GET" }
881
- );
882
- },
883
- getTeamCycleTimeData: async (teamId, range) => {
884
- const r = getResolvedMetricsDateRange(range);
885
- return requestJson(
855
+ `/v1/worktrackingsystemconnections/${connectionId}`,
856
+ {
857
+ method: "PUT",
858
+ body: payload
859
+ }
860
+ ),
861
+ deleteWorkTrackingConnection: async (connectionId) => requestNoContent(
886
862
  configuration,
887
863
  dependencies,
888
- `/v1/teams/${teamId}/metrics/cycleTimeData?${getMetricsDateRangeQuery(r)}`,
889
- { method: "GET" }
890
- );
891
- },
892
- getTeamPredictabilityScore: async (teamId, range, view) => {
893
- const r = getResolvedMetricsDateRange(range);
894
- return requestJson(
864
+ `/v1/worktrackingsystemconnections/${connectionId}`,
865
+ {
866
+ method: "DELETE"
867
+ }
868
+ ),
869
+ listTeams: async () => requestJson(
895
870
  configuration,
896
871
  dependencies,
897
- `/v1/teams/${teamId}/metrics/multiitemforecastpredictabilityscore?${getMetricsDateRangeQuery(r)}${getViewQuerySuffix(view)}`,
898
- { method: "GET" }
899
- );
900
- },
901
- getTeamTotalWorkItemAge: async (teamId, asOfDate) => requestJson(
902
- configuration,
903
- dependencies,
904
- `/v1/teams/${teamId}/metrics/totalWorkItemAge?${getMetricsAsOfDateQuery(asOfDate)}`,
905
- { method: "GET" }
906
- ),
907
- getTeamTotalWorkItemAgeInfo: async (teamId, range) => {
908
- const r = getResolvedMetricsDateRange(range);
909
- return requestJson(
872
+ "/v1/teams",
873
+ {
874
+ method: "GET"
875
+ }
876
+ ),
877
+ getTeam: async (teamId) => requestJson(configuration, dependencies, `/v1/teams/${teamId}`, {
878
+ method: "GET"
879
+ }),
880
+ createTeam: async (payload) => requestJson(configuration, dependencies, "/v1/teams", {
881
+ method: "POST",
882
+ body: payload
883
+ }),
884
+ updateTeam: async (teamId, payload) => requestJson(configuration, dependencies, `/v1/teams/${teamId}`, {
885
+ method: "PUT",
886
+ body: payload
887
+ }),
888
+ deleteTeam: async (teamId) => requestNoContent(configuration, dependencies, `/v1/teams/${teamId}`, {
889
+ method: "DELETE"
890
+ }),
891
+ refreshTeam: async (teamId) => requestNoContent(configuration, dependencies, `/v1/teams/${teamId}`, {
892
+ method: "POST"
893
+ }),
894
+ listPortfolios: async () => requestJson(
910
895
  configuration,
911
896
  dependencies,
912
- `/v1/teams/${teamId}/metrics/totalWorkItemAgeInfo?${getMetricsDateRangeQuery(r)}`,
913
- { method: "GET" }
914
- );
915
- },
916
- getTeamWorkItemAgeOverTime: async (teamId, range) => {
917
- const r = getResolvedMetricsDateRange(range);
918
- const wipResult = await requestJson(
897
+ "/v1/portfolios",
898
+ {
899
+ method: "GET"
900
+ }
901
+ ),
902
+ getPortfolio: async (portfolioId) => requestJson(
919
903
  configuration,
920
904
  dependencies,
921
- `/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
922
- { method: "GET" }
923
- );
924
- if (!wipResult.ok) {
925
- return wipResult;
926
- }
927
- return {
928
- ok: true,
929
- value: deriveWorkItemAgeOverTime(r.startDate, r.endDate, wipResult.value)
930
- };
931
- },
932
- getTeamTotalWorkItemAgeOverTime: async (teamId, range) => {
933
- const r = getResolvedMetricsDateRange(range);
934
- const wipResult = await requestJson(
905
+ `/v1/portfolios/${portfolioId}`,
906
+ {
907
+ method: "GET"
908
+ }
909
+ ),
910
+ createPortfolio: async (payload) => requestJson(configuration, dependencies, "/v1/portfolios", {
911
+ method: "POST",
912
+ body: payload
913
+ }),
914
+ updatePortfolio: async (portfolioId, payload) => requestJson(
935
915
  configuration,
936
916
  dependencies,
937
- `/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
938
- { method: "GET" }
939
- );
940
- if (!wipResult.ok) {
941
- return wipResult;
942
- }
943
- return {
944
- ok: true,
945
- value: deriveTotalWorkItemAgeOverTime(
946
- r.startDate,
947
- r.endDate,
948
- wipResult.value
949
- )
950
- };
951
- },
952
- getPortfolioThroughput: async (portfolioId, range) => {
953
- const r = getResolvedMetricsDateRange(range);
954
- return requestJson(
917
+ `/v1/portfolios/${portfolioId}`,
918
+ {
919
+ method: "PUT",
920
+ body: payload
921
+ }
922
+ ),
923
+ deletePortfolio: async (portfolioId) => requestNoContent(
955
924
  configuration,
956
925
  dependencies,
957
- `/v1/portfolios/${portfolioId}/metrics/throughput?${getMetricsDateRangeQuery(r)}`,
958
- { method: "GET" }
959
- );
960
- },
961
- getPortfolioCycleTimePercentiles: async (portfolioId, range) => {
962
- const r = getResolvedMetricsDateRange(range);
963
- return requestJson(
926
+ `/v1/portfolios/${portfolioId}`,
927
+ {
928
+ method: "DELETE"
929
+ }
930
+ ),
931
+ refreshPortfolio: async (portfolioId) => requestNoContent(
964
932
  configuration,
965
933
  dependencies,
966
- `/v1/portfolios/${portfolioId}/metrics/cycleTimePercentiles?${getMetricsDateRangeQuery(r)}`,
967
- { method: "GET" }
968
- );
969
- },
970
- getPortfolioArrivals: async (portfolioId, range) => {
971
- const r = getResolvedMetricsDateRange(range);
972
- return requestJson(
934
+ `/v1/portfolios/${portfolioId}/refresh`,
935
+ {
936
+ method: "POST"
937
+ }
938
+ ),
939
+ getTeamThroughput: async (teamId, range, view) => {
940
+ const r = getResolvedMetricsDateRange(range);
941
+ return requestJson(
942
+ configuration,
943
+ dependencies,
944
+ `/v1/teams/${teamId}/metrics/throughput?${getMetricsDateRangeQuery(r)}${getViewQuerySuffix(view)}`,
945
+ { method: "GET" }
946
+ );
947
+ },
948
+ getTeamArrivals: async (teamId, range) => {
949
+ const r = getResolvedMetricsDateRange(range);
950
+ return requestJson(
951
+ configuration,
952
+ dependencies,
953
+ `/v1/teams/${teamId}/metrics/arrivals?${getMetricsDateRangeQuery(r)}`,
954
+ { method: "GET" }
955
+ );
956
+ },
957
+ getTeamWipOverTime: async (teamId, range) => {
958
+ const r = getResolvedMetricsDateRange(range);
959
+ return requestJson(
960
+ configuration,
961
+ dependencies,
962
+ `/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
963
+ { method: "GET" }
964
+ );
965
+ },
966
+ getTeamWip: async (teamId, asOfDate) => requestJson(
973
967
  configuration,
974
968
  dependencies,
975
- `/v1/portfolios/${portfolioId}/metrics/arrivals?${getMetricsDateRangeQuery(r)}`,
969
+ `/v1/teams/${teamId}/metrics/wip?${getMetricsAsOfDateQuery(asOfDate)}`,
976
970
  { method: "GET" }
977
- );
978
- },
979
- getPortfolioWipOverTime: async (portfolioId, range) => {
980
- const r = getResolvedMetricsDateRange(range);
981
- return requestJson(
971
+ ),
972
+ getTeamCycleTimePercentiles: async (teamId, range) => {
973
+ const r = getResolvedMetricsDateRange(range);
974
+ return requestJson(
975
+ configuration,
976
+ dependencies,
977
+ `/v1/teams/${teamId}/metrics/cycleTimePercentiles?${getMetricsDateRangeQuery(r)}`,
978
+ { method: "GET" }
979
+ );
980
+ },
981
+ getTeamCycleTimeData: async (teamId, range) => {
982
+ const r = getResolvedMetricsDateRange(range);
983
+ return requestJson(
984
+ configuration,
985
+ dependencies,
986
+ `/v1/teams/${teamId}/metrics/cycleTimeData?${getMetricsDateRangeQuery(r)}`,
987
+ { method: "GET" }
988
+ );
989
+ },
990
+ getTeamPredictabilityScore: async (teamId, range, view) => {
991
+ const r = getResolvedMetricsDateRange(range);
992
+ return requestJson(
993
+ configuration,
994
+ dependencies,
995
+ `/v1/teams/${teamId}/metrics/multiitemforecastpredictabilityscore?${getMetricsDateRangeQuery(r)}${getViewQuerySuffix(view)}`,
996
+ { method: "GET" }
997
+ );
998
+ },
999
+ getTeamTotalWorkItemAge: async (teamId, asOfDate) => requestJson(
982
1000
  configuration,
983
1001
  dependencies,
984
- `/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1002
+ `/v1/teams/${teamId}/metrics/totalWorkItemAge?${getMetricsAsOfDateQuery(asOfDate)}`,
985
1003
  { method: "GET" }
986
- );
987
- },
988
- getPortfolioWip: async (portfolioId, asOfDate) => requestJson(
989
- configuration,
990
- dependencies,
991
- `/v1/portfolios/${portfolioId}/metrics/wip?${getMetricsAsOfDateQuery(asOfDate)}`,
992
- { method: "GET" }
993
- ),
994
- getPortfolioCycleTimeData: async (portfolioId, range) => {
995
- const r = getResolvedMetricsDateRange(range);
996
- return requestJson(
1004
+ ),
1005
+ getTeamTotalWorkItemAgeInfo: async (teamId, range) => {
1006
+ const r = getResolvedMetricsDateRange(range);
1007
+ return requestJson(
1008
+ configuration,
1009
+ dependencies,
1010
+ `/v1/teams/${teamId}/metrics/totalWorkItemAgeInfo?${getMetricsDateRangeQuery(r)}`,
1011
+ { method: "GET" }
1012
+ );
1013
+ },
1014
+ getTeamWorkItemAgeOverTime: async (teamId, range) => {
1015
+ const r = getResolvedMetricsDateRange(range);
1016
+ const wipResult = await requestJson(
1017
+ configuration,
1018
+ dependencies,
1019
+ `/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1020
+ { method: "GET" }
1021
+ );
1022
+ if (!wipResult.ok) {
1023
+ return wipResult;
1024
+ }
1025
+ return {
1026
+ ok: true,
1027
+ value: deriveWorkItemAgeOverTime(
1028
+ r.startDate,
1029
+ r.endDate,
1030
+ wipResult.value
1031
+ )
1032
+ };
1033
+ },
1034
+ getTeamTotalWorkItemAgeOverTime: async (teamId, range) => {
1035
+ const r = getResolvedMetricsDateRange(range);
1036
+ const wipResult = await requestJson(
1037
+ configuration,
1038
+ dependencies,
1039
+ `/v1/teams/${teamId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1040
+ { method: "GET" }
1041
+ );
1042
+ if (!wipResult.ok) {
1043
+ return wipResult;
1044
+ }
1045
+ return {
1046
+ ok: true,
1047
+ value: deriveTotalWorkItemAgeOverTime(
1048
+ r.startDate,
1049
+ r.endDate,
1050
+ wipResult.value
1051
+ )
1052
+ };
1053
+ },
1054
+ getPortfolioThroughput: async (portfolioId, range) => {
1055
+ const r = getResolvedMetricsDateRange(range);
1056
+ return requestJson(
1057
+ configuration,
1058
+ dependencies,
1059
+ `/v1/portfolios/${portfolioId}/metrics/throughput?${getMetricsDateRangeQuery(r)}`,
1060
+ { method: "GET" }
1061
+ );
1062
+ },
1063
+ getPortfolioCycleTimePercentiles: async (portfolioId, range) => {
1064
+ const r = getResolvedMetricsDateRange(range);
1065
+ return requestJson(
1066
+ configuration,
1067
+ dependencies,
1068
+ `/v1/portfolios/${portfolioId}/metrics/cycleTimePercentiles?${getMetricsDateRangeQuery(r)}`,
1069
+ { method: "GET" }
1070
+ );
1071
+ },
1072
+ getPortfolioArrivals: async (portfolioId, range) => {
1073
+ const r = getResolvedMetricsDateRange(range);
1074
+ return requestJson(
1075
+ configuration,
1076
+ dependencies,
1077
+ `/v1/portfolios/${portfolioId}/metrics/arrivals?${getMetricsDateRangeQuery(r)}`,
1078
+ { method: "GET" }
1079
+ );
1080
+ },
1081
+ getPortfolioWipOverTime: async (portfolioId, range) => {
1082
+ const r = getResolvedMetricsDateRange(range);
1083
+ return requestJson(
1084
+ configuration,
1085
+ dependencies,
1086
+ `/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1087
+ { method: "GET" }
1088
+ );
1089
+ },
1090
+ getPortfolioWip: async (portfolioId, asOfDate) => requestJson(
997
1091
  configuration,
998
1092
  dependencies,
999
- `/v1/portfolios/${portfolioId}/metrics/cycleTimeData?${getMetricsDateRangeQuery(r)}`,
1093
+ `/v1/portfolios/${portfolioId}/metrics/wip?${getMetricsAsOfDateQuery(asOfDate)}`,
1000
1094
  { method: "GET" }
1001
- );
1002
- },
1003
- getPortfolioPredictabilityScore: async (portfolioId, range) => {
1004
- const r = getResolvedMetricsDateRange(range);
1005
- return requestJson(
1095
+ ),
1096
+ getPortfolioCycleTimeData: async (portfolioId, range) => {
1097
+ const r = getResolvedMetricsDateRange(range);
1098
+ return requestJson(
1099
+ configuration,
1100
+ dependencies,
1101
+ `/v1/portfolios/${portfolioId}/metrics/cycleTimeData?${getMetricsDateRangeQuery(r)}`,
1102
+ { method: "GET" }
1103
+ );
1104
+ },
1105
+ getPortfolioPredictabilityScore: async (portfolioId, range) => {
1106
+ const r = getResolvedMetricsDateRange(range);
1107
+ return requestJson(
1108
+ configuration,
1109
+ dependencies,
1110
+ `/v1/portfolios/${portfolioId}/metrics/multiitemforecastpredictabilityscore?${getMetricsDateRangeQuery(r)}`,
1111
+ { method: "GET" }
1112
+ );
1113
+ },
1114
+ getPortfolioTotalWorkItemAge: async (portfolioId, asOfDate) => requestJson(
1006
1115
  configuration,
1007
1116
  dependencies,
1008
- `/v1/portfolios/${portfolioId}/metrics/multiitemforecastpredictabilityscore?${getMetricsDateRangeQuery(r)}`,
1117
+ `/v1/portfolios/${portfolioId}/metrics/totalWorkItemAge?${getMetricsAsOfDateQuery(asOfDate)}`,
1009
1118
  { method: "GET" }
1010
- );
1011
- },
1012
- getPortfolioTotalWorkItemAge: async (portfolioId, asOfDate) => requestJson(
1013
- configuration,
1014
- dependencies,
1015
- `/v1/portfolios/${portfolioId}/metrics/totalWorkItemAge?${getMetricsAsOfDateQuery(asOfDate)}`,
1016
- { method: "GET" }
1017
- ),
1018
- getPortfolioTotalWorkItemAgeInfo: async (portfolioId, range) => {
1019
- const r = getResolvedMetricsDateRange(range);
1020
- return requestJson(
1119
+ ),
1120
+ getPortfolioTotalWorkItemAgeInfo: async (portfolioId, range) => {
1121
+ const r = getResolvedMetricsDateRange(range);
1122
+ return requestJson(
1123
+ configuration,
1124
+ dependencies,
1125
+ `/v1/portfolios/${portfolioId}/metrics/totalWorkItemAgeInfo?${getMetricsDateRangeQuery(r)}`,
1126
+ { method: "GET" }
1127
+ );
1128
+ },
1129
+ getPortfolioWorkItemAgeOverTime: async (portfolioId, range) => {
1130
+ const r = getResolvedMetricsDateRange(range);
1131
+ const wipResult = await requestJson(
1132
+ configuration,
1133
+ dependencies,
1134
+ `/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1135
+ { method: "GET" }
1136
+ );
1137
+ if (!wipResult.ok) {
1138
+ return wipResult;
1139
+ }
1140
+ return {
1141
+ ok: true,
1142
+ value: deriveWorkItemAgeOverTime(
1143
+ r.startDate,
1144
+ r.endDate,
1145
+ wipResult.value
1146
+ )
1147
+ };
1148
+ },
1149
+ getPortfolioTotalWorkItemAgeOverTime: async (portfolioId, range) => {
1150
+ const r = getResolvedMetricsDateRange(range);
1151
+ const wipResult = await requestJson(
1152
+ configuration,
1153
+ dependencies,
1154
+ `/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1155
+ { method: "GET" }
1156
+ );
1157
+ if (!wipResult.ok) {
1158
+ return wipResult;
1159
+ }
1160
+ return {
1161
+ ok: true,
1162
+ value: deriveTotalWorkItemAgeOverTime(
1163
+ r.startDate,
1164
+ r.endDate,
1165
+ wipResult.value
1166
+ )
1167
+ };
1168
+ },
1169
+ getTeamCumulativeStateTime: async (teamId, range, itemIds) => {
1170
+ const unsupported = await ensureServerSupports("cumulativeStateTime");
1171
+ if (unsupported) {
1172
+ return unsupported;
1173
+ }
1174
+ const r = getResolvedMetricsDateRange(range);
1175
+ return requestJson(
1176
+ configuration,
1177
+ dependencies,
1178
+ `/v1/teams/${teamId}/metrics/cumulativeStateTime?${getMetricsDateRangeQuery(r)}${getItemIdsQuerySuffix(itemIds)}`,
1179
+ { method: "GET" }
1180
+ );
1181
+ },
1182
+ getTeamCumulativeStateTimeItems: async (teamId, state, range, itemIds) => {
1183
+ const unsupported = await ensureServerSupports("cumulativeStateTime");
1184
+ if (unsupported) {
1185
+ return unsupported;
1186
+ }
1187
+ const r = getResolvedMetricsDateRange(range);
1188
+ return requestJson(
1189
+ configuration,
1190
+ dependencies,
1191
+ `/v1/teams/${teamId}/metrics/cumulativeStateTime/items?state=${encodeURIComponent(state)}&${getMetricsDateRangeQuery(r)}${getItemIdsQuerySuffix(itemIds)}`,
1192
+ { method: "GET" }
1193
+ );
1194
+ },
1195
+ getTeamCumulativeStateTimeCandidates: async (teamId, range) => {
1196
+ const unsupported = await ensureServerSupports("cumulativeStateTime");
1197
+ if (unsupported) {
1198
+ return unsupported;
1199
+ }
1200
+ const r = getResolvedMetricsDateRange(range);
1201
+ return requestJson(
1202
+ configuration,
1203
+ dependencies,
1204
+ `/v1/teams/${teamId}/metrics/cumulativeStateTime/candidates?${getMetricsDateRangeQuery(r)}`,
1205
+ { method: "GET" }
1206
+ );
1207
+ },
1208
+ getPortfolioCumulativeStateTime: async (portfolioId, range, itemIds) => {
1209
+ const unsupported = await ensureServerSupports("cumulativeStateTime");
1210
+ if (unsupported) {
1211
+ return unsupported;
1212
+ }
1213
+ const r = getResolvedMetricsDateRange(range);
1214
+ return requestJson(
1215
+ configuration,
1216
+ dependencies,
1217
+ `/v1/portfolios/${portfolioId}/metrics/cumulativeStateTime?${getMetricsDateRangeQuery(r)}${getItemIdsQuerySuffix(itemIds)}`,
1218
+ { method: "GET" }
1219
+ );
1220
+ },
1221
+ getPortfolioCumulativeStateTimeItems: async (portfolioId, state, range, itemIds) => {
1222
+ const unsupported = await ensureServerSupports("cumulativeStateTime");
1223
+ if (unsupported) {
1224
+ return unsupported;
1225
+ }
1226
+ const r = getResolvedMetricsDateRange(range);
1227
+ return requestJson(
1228
+ configuration,
1229
+ dependencies,
1230
+ `/v1/portfolios/${portfolioId}/metrics/cumulativeStateTime/items?state=${encodeURIComponent(state)}&${getMetricsDateRangeQuery(r)}${getItemIdsQuerySuffix(itemIds)}`,
1231
+ { method: "GET" }
1232
+ );
1233
+ },
1234
+ getPortfolioCumulativeStateTimeCandidates: async (portfolioId, range) => {
1235
+ const unsupported = await ensureServerSupports("cumulativeStateTime");
1236
+ if (unsupported) {
1237
+ return unsupported;
1238
+ }
1239
+ const r = getResolvedMetricsDateRange(range);
1240
+ return requestJson(
1241
+ configuration,
1242
+ dependencies,
1243
+ `/v1/portfolios/${portfolioId}/metrics/cumulativeStateTime/candidates?${getMetricsDateRangeQuery(r)}`,
1244
+ { method: "GET" }
1245
+ );
1246
+ },
1247
+ getFeaturesByIds: async (ids) => {
1248
+ const queryString = ids.map((id) => `ids=${encodeURIComponent(id)}`).join("&");
1249
+ return requestJson(
1250
+ configuration,
1251
+ dependencies,
1252
+ `/v1/features?${queryString}`,
1253
+ { method: "GET" }
1254
+ );
1255
+ },
1256
+ getFeaturesByReferences: async (refs) => {
1257
+ const queryString = refs.map((r) => `featureReferences=${encodeURIComponent(r)}`).join("&");
1258
+ return requestJson(
1259
+ configuration,
1260
+ dependencies,
1261
+ `/v1/features/references?${queryString}`,
1262
+ { method: "GET" }
1263
+ );
1264
+ },
1265
+ getFeatureWorkItems: async (featureId) => requestJson(
1021
1266
  configuration,
1022
1267
  dependencies,
1023
- `/v1/portfolios/${portfolioId}/metrics/totalWorkItemAgeInfo?${getMetricsDateRangeQuery(r)}`,
1268
+ `/v1/features/${featureId}/workitems`,
1024
1269
  { method: "GET" }
1025
- );
1026
- },
1027
- getPortfolioWorkItemAgeOverTime: async (portfolioId, range) => {
1028
- const r = getResolvedMetricsDateRange(range);
1029
- const wipResult = await requestJson(
1270
+ ),
1271
+ listDeliveries: async (portfolioId) => requestJson(
1030
1272
  configuration,
1031
1273
  dependencies,
1032
- `/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1274
+ `/v1/deliveries/portfolio/${portfolioId}`,
1033
1275
  { method: "GET" }
1034
- );
1035
- if (!wipResult.ok) {
1036
- return wipResult;
1037
- }
1038
- return {
1039
- ok: true,
1040
- value: deriveWorkItemAgeOverTime(r.startDate, r.endDate, wipResult.value)
1041
- };
1042
- },
1043
- getPortfolioTotalWorkItemAgeOverTime: async (portfolioId, range) => {
1044
- const r = getResolvedMetricsDateRange(range);
1045
- const wipResult = await requestJson(
1276
+ ),
1277
+ createDelivery: async (portfolioId, payload) => requestJson(
1046
1278
  configuration,
1047
1279
  dependencies,
1048
- `/v1/portfolios/${portfolioId}/metrics/wipOverTime?${getMetricsDateRangeQuery(r)}`,
1049
- { method: "GET" }
1050
- );
1051
- if (!wipResult.ok) {
1052
- return wipResult;
1053
- }
1054
- return {
1055
- ok: true,
1056
- value: deriveTotalWorkItemAgeOverTime(
1057
- r.startDate,
1058
- r.endDate,
1059
- wipResult.value
1060
- )
1061
- };
1062
- },
1063
- getFeaturesByIds: async (ids) => {
1064
- const queryString = ids.map((id) => `ids=${encodeURIComponent(id)}`).join("&");
1065
- return requestJson(
1280
+ `/v1/deliveries/portfolio/${portfolioId}`,
1281
+ { method: "POST", body: payload }
1282
+ ),
1283
+ updateDelivery: async (deliveryId, payload) => requestJson(
1066
1284
  configuration,
1067
1285
  dependencies,
1068
- `/v1/features?${queryString}`,
1069
- { method: "GET" }
1070
- );
1071
- },
1072
- getFeaturesByReferences: async (refs) => {
1073
- const queryString = refs.map((r) => `featureReferences=${encodeURIComponent(r)}`).join("&");
1074
- return requestJson(
1286
+ `/v1/deliveries/${deliveryId}`,
1287
+ { method: "PUT", body: payload }
1288
+ ),
1289
+ deleteDelivery: async (deliveryId) => requestNoContent(
1075
1290
  configuration,
1076
1291
  dependencies,
1077
- `/v1/features/references?${queryString}`,
1078
- { method: "GET" }
1079
- );
1080
- },
1081
- getFeatureWorkItems: async (featureId) => requestJson(
1082
- configuration,
1083
- dependencies,
1084
- `/v1/features/${featureId}/workitems`,
1085
- { method: "GET" }
1086
- ),
1087
- listDeliveries: async (portfolioId) => requestJson(
1088
- configuration,
1089
- dependencies,
1090
- `/v1/deliveries/portfolio/${portfolioId}`,
1091
- { method: "GET" }
1092
- ),
1093
- createDelivery: async (portfolioId, payload) => requestJson(
1094
- configuration,
1095
- dependencies,
1096
- `/v1/deliveries/portfolio/${portfolioId}`,
1097
- { method: "POST", body: payload }
1098
- ),
1099
- updateDelivery: async (deliveryId, payload) => requestJson(
1100
- configuration,
1101
- dependencies,
1102
- `/v1/deliveries/${deliveryId}`,
1103
- { method: "PUT", body: payload }
1104
- ),
1105
- deleteDelivery: async (deliveryId) => requestNoContent(
1106
- configuration,
1107
- dependencies,
1108
- `/v1/deliveries/${deliveryId}`,
1109
- { method: "DELETE" }
1110
- ),
1111
- runManualForecast: async (teamId, payload) => requestJson(
1112
- configuration,
1113
- dependencies,
1114
- `/v1/forecast/manual/${teamId}`,
1115
- { method: "POST", body: payload }
1116
- ),
1117
- runBacktest: async (teamId, payload) => requestJson(
1118
- configuration,
1119
- dependencies,
1120
- `/v1/forecast/backtest/${teamId}`,
1121
- { method: "POST", body: payload }
1122
- )
1123
- });
1292
+ `/v1/deliveries/${deliveryId}`,
1293
+ { method: "DELETE" }
1294
+ ),
1295
+ getRecurringBlackoutRules: async () => {
1296
+ const unsupported = await ensureServerSupports("recurringBlackoutRules");
1297
+ if (unsupported) {
1298
+ return unsupported;
1299
+ }
1300
+ return requestJson(
1301
+ configuration,
1302
+ dependencies,
1303
+ "/v1/recurring-blackout-rules",
1304
+ { method: "GET" }
1305
+ );
1306
+ },
1307
+ createRecurringBlackoutRule: async (payload) => {
1308
+ const unsupported = await ensureServerSupports("recurringBlackoutRules");
1309
+ if (unsupported) {
1310
+ return unsupported;
1311
+ }
1312
+ return requestJson(
1313
+ configuration,
1314
+ dependencies,
1315
+ "/v1/recurring-blackout-rules",
1316
+ { method: "POST", body: payload }
1317
+ );
1318
+ },
1319
+ updateRecurringBlackoutRule: async (id, payload) => {
1320
+ const unsupported = await ensureServerSupports("recurringBlackoutRules");
1321
+ if (unsupported) {
1322
+ return unsupported;
1323
+ }
1324
+ return requestJson(
1325
+ configuration,
1326
+ dependencies,
1327
+ `/v1/recurring-blackout-rules/${id}`,
1328
+ { method: "PUT", body: payload }
1329
+ );
1330
+ },
1331
+ deleteRecurringBlackoutRule: async (id) => {
1332
+ const unsupported = await ensureServerSupports("recurringBlackoutRules");
1333
+ if (unsupported) {
1334
+ return unsupported;
1335
+ }
1336
+ return requestNoContent(
1337
+ configuration,
1338
+ dependencies,
1339
+ `/v1/recurring-blackout-rules/${id}`,
1340
+ { method: "DELETE" }
1341
+ );
1342
+ },
1343
+ runManualForecast: async (teamId, payload) => requestJson(
1344
+ configuration,
1345
+ dependencies,
1346
+ `/v1/forecast/manual/${teamId}`,
1347
+ { method: "POST", body: payload }
1348
+ ),
1349
+ runBacktest: async (teamId, payload) => requestJson(
1350
+ configuration,
1351
+ dependencies,
1352
+ `/v1/forecast/backtest/${teamId}`,
1353
+ { method: "POST", body: payload }
1354
+ )
1355
+ };
1356
+ };
1124
1357
  export {
1125
1358
  createLighthouseAuthContext,
1126
1359
  createLighthouseClient,
1127
1360
  getClientPackageContract,
1128
1361
  getDefaultMetricsDateRange,
1129
1362
  getStandaloneDiscoveryLockfilePath,
1363
+ isServerVersionNewerThan,
1130
1364
  loadStandaloneDiscoveryContract,
1131
1365
  parseStandaloneDiscoveryContract,
1132
1366
  pollCliAuthSession,