Bump date-fns from 2.30.0 to 4.1.0 (#55335)

* Bump date-fns from 2.30.0 to 4.1.0

Bumps [date-fns](https://github.com/date-fns/date-fns) from 2.30.0 to 4.1.0.
- [Release notes](https://github.com/date-fns/date-fns/releases)
- [Changelog](https://github.com/date-fns/date-fns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/date-fns/date-fns/compare/v2.30.0...v4.1.0)

---
updated-dependencies:
- dependency-name: date-fns
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Migrate to named exports

* Remove unused access request code that imported date-fns

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Grzegorz Zdunek <grzegorz.zdunek@goteleport.com>
This commit is contained in:
dependabot[bot]
2025-09-10 14:30:08 +00:00
committed by GitHub
co-authored by Grzegorz Zdunek
parent e73875bb7c
commit 9fb5833b6a
9 changed files with 13 additions and 692 deletions
+1 -1
View File
@@ -77,7 +77,7 @@
"@uiw/react-codemirror": "^4.25.1",
"d3-scale": "^4.0.2",
"d3-time-format": "^4.1.0",
"date-fns": "^2.28.0",
"date-fns": "^4.1.0",
"highlight.js": "^11.11.1",
"history": "^4.9.0",
"immer": "^10.1.1",
+2 -10
View File
@@ -61,8 +61,8 @@ importers:
specifier: ^4.1.0
version: 4.1.0
date-fns:
specifier: ^2.28.0
version: 2.30.0
specifier: ^4.1.0
version: 4.1.0
highlight.js:
specifier: ^11.11.1
version: 11.11.1
@@ -3896,10 +3896,6 @@ packages:
date-fns-jalali@4.1.0-0:
resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==}
date-fns@2.30.0:
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
engines: {node: '>=0.11'}
date-fns@4.1.0:
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
@@ -10911,10 +10907,6 @@ snapshots:
date-fns-jalali@4.1.0-0: {}
date-fns@2.30.0:
dependencies:
'@babel/runtime': 7.28.2
date-fns@4.1.0: {}
debug@4.4.1:
@@ -1,88 +0,0 @@
/**
* Teleport
* Copyright (C) 2023 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { RequestableResourceKind } from 'shared/components/AccessRequests/NewRequest/resource';
import type { Option } from 'shared/components/Select';
export type DurationOption = Option<number>;
export interface Resource {
id: {
kind: RequestableResourceKind;
name: string;
clusterName: string;
subResourceName?: string;
};
details?: {
hostname?: string;
friendlyName?: string;
};
}
type RequestState = 'NONE' | 'PENDING' | 'APPROVED' | 'DENIED' | 'APPLIED' | '';
export interface ResourceId {
kind: RequestableResourceKind;
name: string;
clusterName: string;
subResourceName?: string;
}
export interface AccessRequest {
id: string;
created: Date;
expires: Date;
maxDuration?: Date;
requestReason: string;
resolveReason: string;
resources: Resource[];
reviews: string[];
roles: string[];
sessionTTL?: Date;
state: RequestState;
suggestedReviewers: string[] | null;
thresholdNames: string[];
user: string;
}
export interface CreateAccessRequest {
reason?: string;
roles?: string[];
resourceIds?: ResourceId[];
suggestedReviewers?: string[];
maxDuration?: Date;
dryRun?: boolean;
}
interface AccessRequestResourceBase {
id: string;
type: 'app' | 'node' | 'kubernetes' | 'desktop' | 'database';
}
interface AccessRequestGenericResource extends AccessRequestResourceBase {
type: 'app' | 'kubernetes' | 'desktop' | 'database';
}
interface AccessRequestNodeResource extends AccessRequestResourceBase {
type: 'node';
friendlyName: string;
}
export type AccessRequestResource =
| AccessRequestGenericResource
| AccessRequestNodeResource;
@@ -1,423 +0,0 @@
/**
* Teleport
* Copyright (C) 2023 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Duration } from 'date-fns';
import {
middleValues,
requestTtlMiddleValues,
roundToNearestTenMinutes,
} from 'teleport/AccessRequests/utils';
// Generate testing response
function generateResponse(
currentDate: Date,
values: Array<{
days: number;
hours: number;
minutes: number;
}>
) {
const defaultValues = {
years: 0,
months: 0,
minutes: 0,
seconds: 0,
};
const result = [];
for (let i = 0; i < values.length; i++) {
const { days, hours, minutes } = values[i];
const duration = {
...defaultValues,
days,
hours,
minutes,
};
let d = new Date(currentDate);
d.setDate(currentDate.getDate() + days);
d.setHours(currentDate.getHours() + hours);
d.setMinutes(currentDate.getMinutes() + minutes);
const timestamp = d.getTime();
result.push({
timestamp,
duration,
});
}
return result;
}
describe('generate middle times', () => {
const cases: {
name: string;
created: string;
sessionTTL: string;
maxDuration: string;
expected: Array<{
days: number;
hours: number;
minutes: number;
}>;
}[] = [
{
name: '3 days max',
created: '2021-09-01T00:00:00.000Z',
sessionTTL: '2021-09-01T01:00:00.000Z',
maxDuration: '2021-09-04T00:00:00.000Z',
expected: [
{
days: 0,
hours: 1,
minutes: 0,
},
{
days: 1,
hours: 0,
minutes: 0,
},
{
days: 2,
hours: 0,
minutes: 0,
},
{
days: 3,
hours: 0,
minutes: 0,
},
],
},
{
name: '1 day max',
created: '2021-09-01T00:00:00.000Z',
sessionTTL: '2021-09-01T01:00:00.000Z',
maxDuration: '2021-09-02T00:00:00.000Z',
expected: [
{
days: 0,
hours: 1,
minutes: 0,
},
{
days: 1,
hours: 0,
minutes: 0,
},
],
},
{
name: 'session ttl is 10 min',
created: '2021-09-01T00:00:00.000Z',
sessionTTL: '2021-09-01T00:10:00.000Z',
maxDuration: '2021-09-03T00:00:00.000Z',
expected: [
{
days: 0,
hours: 0,
minutes: 10,
},
{
days: 1,
hours: 0,
minutes: 0,
},
{
days: 2,
hours: 0,
minutes: 0,
},
],
},
{
name: '10 minutes min - real values',
created: '2023-09-21T20:50:52.669012121Z',
sessionTTL: '2023-09-21T21:00:52.669081473Z',
maxDuration: '2023-09-27T20:50:52.669081473Z',
expected: [
{
days: 0,
hours: 0,
minutes: 10,
},
{
days: 1,
hours: 0,
minutes: 0,
},
{
days: 2,
hours: 0,
minutes: 0,
},
{
days: 3,
hours: 0,
minutes: 0,
},
{
days: 4,
hours: 0,
minutes: 0,
},
{
days: 5,
hours: 0,
minutes: 0,
},
{
days: 6,
hours: 0,
minutes: 0,
},
],
},
{
name: 'only one option generated',
created: '2023-09-21T10:00:52.669012121Z',
sessionTTL: '2023-09-21T15:00:52.669081473Z',
maxDuration: '2023-09-21T15:00:52.669081473Z',
expected: [
{
days: 0,
hours: 5,
minutes: 0,
},
],
},
{
name: 'generate all options if max duration is grater than session ttl but less than 1d',
created: '2023-09-21T10:00:52.669012121Z',
sessionTTL: '2023-09-21T15:00:52.669081473Z',
maxDuration: '2023-09-21T17:00:52.669081473Z',
expected: [
{
days: 0,
hours: 5,
minutes: 0,
},
{
days: 0,
hours: 7,
minutes: 0,
},
],
},
];
test.each(cases)(
'$name',
({ sessionTTL, maxDuration, created, expected }) => {
const result = middleValues(
new Date(created),
new Date(sessionTTL),
new Date(maxDuration)
);
expect(result).toEqual(generateResponse(new Date(created), expected));
}
);
});
describe('generate request TTL middle times', () => {
const cases: {
name: string;
created: string;
sessionTTL: string;
expected: Array<{
days: number;
hours: number;
minutes: number;
}>;
}[] = [
{
name: 'max session TTL',
created: '2021-09-01T00:00:00.000Z',
sessionTTL: '2021-09-02T06:00:00.000Z',
expected: [
{
days: 0,
hours: 1,
minutes: 0,
},
{
days: 0,
hours: 2,
minutes: 0,
},
{
days: 0,
hours: 3,
minutes: 0,
},
{
days: 0,
hours: 4,
minutes: 0,
},
{
days: 0,
hours: 6,
minutes: 0,
},
{
days: 0,
hours: 8,
minutes: 0,
},
{
days: 0,
hours: 12,
minutes: 0,
},
{
days: 0,
hours: 18,
minutes: 0,
},
{
days: 1,
hours: 0,
minutes: 0,
},
{
days: 1,
hours: 6,
minutes: 0,
},
],
},
{
name: 'shortest session TTL',
created: '2021-09-01T00:00:00.000Z',
sessionTTL: '2021-09-01T00:30:00.000Z',
expected: [
{
days: 0,
hours: 0,
minutes: 30,
},
],
},
{
name: 'session TTL in middle',
created: '2021-09-01T00:00:00.000Z',
sessionTTL: '2021-09-01T08:30:00.000Z',
expected: [
{
days: 0,
hours: 1,
minutes: 0,
},
{
days: 0,
hours: 2,
minutes: 0,
},
{
days: 0,
hours: 3,
minutes: 0,
},
{
days: 0,
hours: 4,
minutes: 0,
},
{
days: 0,
hours: 6,
minutes: 0,
},
{
days: 0,
hours: 8,
minutes: 0,
},
],
},
];
test.each(cases)('$name', ({ sessionTTL, created, expected }) => {
const result = requestTtlMiddleValues(
new Date(created),
new Date(sessionTTL)
);
expect(result).toEqual(generateResponse(new Date(created), expected));
});
});
describe('round to nearest 10 minutes', () => {
const cases: {
name: string;
input: Duration;
expected: Duration;
}[] = [
{
name: 'round up',
input: { minutes: 9, seconds: 0 },
expected: { minutes: 10, seconds: 0 },
},
{
name: 'round down',
input: { minutes: 11, seconds: 0 },
expected: { minutes: 10, seconds: 0 },
},
{
name: 'round to 10',
input: { minutes: 15, seconds: 0 },
expected: { minutes: 20, seconds: 0 },
},
{
name: 'do not round to 0',
input: { minutes: 1, seconds: 0 },
expected: { minutes: 10, seconds: 0 },
},
{
name: 'round minutes to 0 when days or hours are present',
input: { hours: 3, minutes: 1, seconds: 0 },
expected: { hours: 3, minutes: 0, seconds: 0 },
},
{
name: 'do not round to 0',
input: { minutes: 0, seconds: 0 },
expected: { minutes: 10, seconds: 0 },
},
{
name: 'seconds are removed',
input: { minutes: 9, seconds: 10 },
expected: { minutes: 10, seconds: 0 },
},
{
name: "duration doesn't change when days are present",
input: { days: 1, minutes: 9, seconds: 10 },
expected: { days: 1, minutes: 10, seconds: 0 },
},
{
name: 'add 60 minutes to undefined hour and set minutes to 0',
input: { minutes: 60 },
expected: { hours: 1, minutes: 0, seconds: 0 },
},
{
name: 'add 60 minutes to existing hour and set minutes to 0',
input: { hours: 3, minutes: 60 },
expected: { hours: 4, minutes: 0, seconds: 0 },
},
];
test.each(cases)('$name', ({ input, expected }) => {
const result = roundToNearestTenMinutes(input);
expect(result).toEqual(expected);
});
});
@@ -1,160 +0,0 @@
/**
* Teleport
* Copyright (C) 2023 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {
addDays,
addHours,
Duration,
intervalToDuration,
isAfter,
isBefore,
} from 'date-fns';
type TimeDuration = {
timestamp: number;
duration: Duration;
};
// Round the duration to the nearest 10 minutes
// Example:
// 9m -> 10m
// 10m -> 10m
// 11m -> 10m
// 15m -> 20m
// 1d -> 1d
// 1d 1h -> 1d 1h
// The only exception is 0m, which is rounded to 10m
export function roundToNearestTenMinutes(date: Duration): Duration {
let minutes = date.minutes;
let roundedMinutes = Math.round(minutes / 10) * 10; // Round to the nearest 10
if (roundedMinutes === 0 && !date.days && !date.hours) {
// Do not round down to 0. This
roundedMinutes = 10;
}
// 60 minutes == 1 hour
// Prevent displaying time as eg: `5 hrs and 60 mins`
// to `6 hrs`.
if (roundedMinutes === 60) {
if (!date.hours) {
date.hours = 0;
}
date.hours += 1;
roundedMinutes = 0;
}
date.minutes = roundedMinutes;
date.seconds = 0;
return date;
}
// Generate a list of middle values between start and end. The first value is the
// session TTL that is rounded to the nearest hour. The rest of the values are
// rounded to the nearest day. Example:
//
// created: 2021-09-01T00:00:00.000Z
// start: 2021-09-01T01:00:00.000Z
// end: 2021-09-03T00:00:00.000Z
// now: 2021-09-01T00:00:00.000Z
//
// returns: [1h, 1d, 2d, 3d]
export function middleValues(
created: Date,
start: Date,
end: Date
): TimeDuration[] {
const getInterval = (d: Date) =>
roundToNearestTenMinutes(
intervalToDuration({
start: created,
end: d,
})
);
const points: Date[] = [start];
if (isAfter(addDays(created, 1), end)) {
// Add all possible options to the list. This covers the case when the
// max duration is less than 24 hours.
if (isBefore(addHours(points[points.length - 1], 1), end)) {
points.push(end);
}
return points.map(d => ({
timestamp: d.getTime(),
duration: getInterval(d),
}));
}
points.push(addDays(created, 1));
// I also prefer while(true), but our linter doesn't
for (;;) {
const next = addHours(points[points.length - 1], 24);
// Allow next == end
if (next > end) {
break;
}
points.push(next);
}
return points.map(d => ({
timestamp: d.getTime(),
duration: getInterval(d),
}));
}
// Generate a list of middle values between now and the request TTL.
export function requestTtlMiddleValues(
created: Date,
requestTtl: Date
): TimeDuration[] {
const getInterval = (d: Date) =>
roundToNearestTenMinutes(
intervalToDuration({
start: created,
end: d,
})
);
if (isAfter(addHours(created, 1), requestTtl)) {
return [
{
timestamp: requestTtl.getTime(),
duration: getInterval(requestTtl),
},
];
}
const points: Date[] = [];
// Staggered hour options, up to 1 week.
const hourOptions = [1, 2, 3, 4, 6, 8, 12, 18, 24, 30, 168];
for (const h of hourOptions) {
const t = addHours(created, h);
if (isAfter(t, requestTtl)) {
break;
}
points.push(t);
}
return points.map(d => ({
timestamp: d.getTime(),
duration: getInterval(d),
}));
}
@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import format from 'date-fns/format';
import formatDistanceToNowStrict from 'date-fns/formatDistanceToNowStrict';
import parseISO from 'date-fns/parseISO';
import { format } from 'date-fns/format';
import { formatDistanceToNowStrict } from 'date-fns/formatDistanceToNowStrict';
import { parseISO } from 'date-fns/parseISO';
import styled from 'styled-components';
import { Info } from 'design/Alert/Alert';
@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import format from 'date-fns/format';
import formatDistanceToNowStrict from 'date-fns/formatDistanceToNowStrict';
import parseISO from 'date-fns/parseISO';
import { format } from 'date-fns/format';
import { formatDistanceToNowStrict } from 'date-fns/formatDistanceToNowStrict';
import { parseISO } from 'date-fns/parseISO';
import { ReactElement } from 'react';
import styled from 'styled-components';
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import format from 'date-fns/format';
import parseISO from 'date-fns/parseISO';
import { format } from 'date-fns/format';
import { parseISO } from 'date-fns/parseISO';
import styled from 'styled-components';
import Flex from 'design/Flex/Flex';
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import format from 'date-fns/format';
import parseISO from 'date-fns/parseISO';
import { format } from 'date-fns/format';
import { parseISO } from 'date-fns/parseISO';
import { MouseEventHandler } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';