From dad416789356fcc2020c43bc3349a354184aa14b Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Tue, 14 Apr 2026 14:34:19 +0100 Subject: [PATCH 1/4] Remove Active/Maintenance LTS distinction --- .../Downloads/Release/VersionDropdown.tsx | 11 +++-- .../PreviousReleasesTable/TableBody.tsx | 6 +-- .../Releases/ReleaseOverview/index.tsx | 2 +- apps/site/components/withDownloadSection.tsx | 4 +- apps/site/components/withFooter.tsx | 2 +- apps/site/components/withReleaseAlertBox.tsx | 3 +- .../generators/__tests__/releaseData.test.mjs | 2 +- .../site/next-data/generators/releaseData.mjs | 42 ++++++------------- .../scripts/orama-search/get-documents.mjs | 8 ++-- apps/site/types/releases.ts | 13 +----- apps/site/util/download/constants.json | 10 +---- 11 files changed, 35 insertions(+), 68 deletions(-) diff --git a/apps/site/components/Downloads/Release/VersionDropdown.tsx b/apps/site/components/Downloads/Release/VersionDropdown.tsx index 3ca72e9b9b8ce..fda9bb21aa6f8 100644 --- a/apps/site/components/Downloads/Release/VersionDropdown.tsx +++ b/apps/site/components/Downloads/Release/VersionDropdown.tsx @@ -10,10 +10,11 @@ import { ReleasesContext, } from '#site/providers/releaseProvider'; +import type { NodeReleaseStatus } from '#site/types/releases.js'; import type { FC } from 'react'; -const getDropDownStatus = (version: string, status: string) => { - if (status.endsWith('LTS')) { +const getDropDownStatus = (version: string, status: NodeReleaseStatus) => { + if (status === 'LTS') { return `${version} (LTS)`; } @@ -21,6 +22,10 @@ const getDropDownStatus = (version: string, status: string) => { return `${version} (Current)`; } + if (status === 'End-of-life') { + return `${version} (EoL)`; + } + return version; }; @@ -38,7 +43,7 @@ const VersionDropdown: FC = () => { ({ versionWithPrefix }) => versionWithPrefix === version ); - if (release?.isLts && pathname.includes('current')) { + if (release?.status === 'LTS' && pathname.includes('current')) { redirect({ href: '/download', locale }); return; } diff --git a/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx b/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx index 0d91d28b00339..742101abacaa2 100644 --- a/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx +++ b/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx @@ -15,10 +15,8 @@ import ReleaseModal from '../ReleaseModal'; const BADGE_KIND_MAP = { 'End-of-life': 'warning', - 'Maintenance LTS': 'neutral', - 'Active LTS': 'info', + LTS: 'info', Current: 'default', - Pending: 'default', } as const; type PreviousReleasesTableBodyProps = { @@ -50,7 +48,7 @@ const PreviousReleasesTableBody: FC = ({ - + diff --git a/apps/site/components/Releases/ReleaseOverview/index.tsx b/apps/site/components/Releases/ReleaseOverview/index.tsx index b3f5b3ed65b22..a77ddc1558695 100644 --- a/apps/site/components/Releases/ReleaseOverview/index.tsx +++ b/apps/site/components/Releases/ReleaseOverview/index.tsx @@ -28,7 +28,7 @@ const ReleaseOverview: FC = ({ release }) => {
} + title={} subtitle={t('components.releaseOverview.firstReleased')} /> diff --git a/apps/site/components/withDownloadSection.tsx b/apps/site/components/withDownloadSection.tsx index be825e39f2ef3..373eebaafb290 100644 --- a/apps/site/components/withDownloadSection.tsx +++ b/apps/site/components/withDownloadSection.tsx @@ -39,9 +39,7 @@ const WithDownloadSection: FC = async ({ .concat(localeSnippets); // Decides which initial release to use based on the current pathname - const initialRelease = pathname.endsWith('/current') - ? 'Current' - : ['Active LTS' as const, 'Maintenance LTS' as const]; + const initialRelease = pathname.endsWith('/current') ? 'Current' : 'LTS'; return ( diff --git a/apps/site/components/withFooter.tsx b/apps/site/components/withFooter.tsx index 72a200ccb18df..148aa7e65e08f 100644 --- a/apps/site/components/withFooter.tsx +++ b/apps/site/components/withFooter.tsx @@ -27,7 +27,7 @@ const WithFooter: FC = () => { const primary = (
- + {({ release }) => ( = ({ status }) => { })} ); - case 'Active LTS': - case 'Maintenance LTS': + case 'LTS': return ( { version: '14.0.0', versionWithPrefix: 'v14.0.0', codename: '', - isLts: false, npm: '6.14.10', v8: '8.0.276.20', releaseDate: '2021-04-20', + initialDate: '2021-04-20', modules: '83', status: 'End-of-life', }); diff --git a/apps/site/next-data/generators/releaseData.mjs b/apps/site/next-data/generators/releaseData.mjs index b6db33b949f2d..612ba212d9ceb 100644 --- a/apps/site/next-data/generators/releaseData.mjs +++ b/apps/site/next-data/generators/releaseData.mjs @@ -3,31 +3,18 @@ import getMajorNodeReleases from './majorNodeReleases.mjs'; // Gets the appropriate release status for each major release -const getNodeReleaseStatus = (latest, support) => { +const getNodeReleaseStatus = (latest, eol) => { const now = new Date(); - const { endOfLife, maintenanceStart, ltsStart, currentStart } = support; - if (endOfLife && now >= new Date(endOfLife)) { + if (eol && now >= new Date(eol)) { return 'End-of-life'; } - if ( - latest.lts.isLts && - maintenanceStart && - now >= new Date(maintenanceStart) - ) { - return 'Maintenance LTS'; + if (latest.lts.isLts) { + return 'LTS'; } - if (latest.lts.isLts && ltsStart && now >= new Date(ltsStart)) { - return 'Active LTS'; - } - - if (currentStart && now >= new Date(currentStart)) { - return 'Current'; - } - - return 'Pending'; + return 'Current'; }; /** @@ -40,17 +27,15 @@ const generateReleaseData = async () => { const majors = await getMajorNodeReleases(); return majors.map(([, major]) => { - const [latestVersion] = Object.values(major.releases); - - const support = { - currentStart: major.support.phases.dates.start, - ltsStart: major.support.phases.dates.lts, - maintenanceStart: major.support.phases.dates.maintenance, - endOfLife: major.support.phases.dates.end, - }; + const versions = Object.values(major.releases); + const latestVersion = versions[0]; + const initialVersion = versions[versions.length - 1]; // Get the major release status based on our Release Schedule - const status = getNodeReleaseStatus(latestVersion, support); + const status = getNodeReleaseStatus( + latestVersion, + major.support.phases.dates.end + ); const minorVersions = Object.entries(major.releases).map(([, release]) => ({ modules: release.modules.version || '', @@ -62,16 +47,15 @@ const generateReleaseData = async () => { })); return { - ...support, status, major: latestVersion.semver.major, version: latestVersion.semver.raw, versionWithPrefix: `v${latestVersion.semver.raw}`, codename: major.support.codename || '', - isLts: status.endsWith('LTS'), npm: latestVersion.dependencies.npm || '', v8: latestVersion.dependencies.v8, releaseDate: latestVersion.releaseDate, + initialDate: initialVersion.releaseDate, modules: latestVersion.modules.version || '', minorVersions, }; diff --git a/apps/site/scripts/orama-search/get-documents.mjs b/apps/site/scripts/orama-search/get-documents.mjs index 0363ff4e2358c..bd374421520d5 100644 --- a/apps/site/scripts/orama-search/get-documents.mjs +++ b/apps/site/scripts/orama-search/get-documents.mjs @@ -13,17 +13,15 @@ const fetchOptions = process.env.GITHUB_TOKEN /** * Fetch Node.js API documentation directly from GitHub - * for the current Active LTS version. + * for the current LTS version. */ export const getAPIDocs = async () => { // Find the current Active LTS version const releaseData = await generateReleaseData(); - const ltsRelease = - releaseData.find(r => r.status === 'Active LTS') || - releaseData.find(r => r.status === 'Maintenance LTS'); + const ltsRelease = releaseData.find(r => r.status === 'LTS'); if (!ltsRelease) { - throw new Error('No Active LTS or Maintenance LTS release found'); + throw new Error('No LTS release found'); } // Get list of API docs from the Node.js repo diff --git a/apps/site/types/releases.ts b/apps/site/types/releases.ts index 37d9cec716e40..38d29bdf20469 100644 --- a/apps/site/types/releases.ts +++ b/apps/site/types/releases.ts @@ -1,21 +1,13 @@ -export type NodeReleaseStatus = - | 'Active LTS' - | 'Maintenance LTS' - | 'Current' - | 'End-of-life' - | 'Pending'; +export type NodeReleaseStatus = 'LTS' | 'Current' | 'End-of-life'; export type NodeReleaseSource = { major: number; version: string; codename?: string; - currentStart: string; - ltsStart?: string; - maintenanceStart?: string; - endOfLife: string; npm?: string; v8: string; releaseDate: string; + initialDate: string; modules?: string; }; @@ -30,7 +22,6 @@ export type MinorVersion = { export type NodeRelease = { versionWithPrefix: string; - isLts: boolean; status: NodeReleaseStatus; minorVersions: Array; } & NodeReleaseSource; diff --git a/apps/site/util/download/constants.json b/apps/site/util/download/constants.json index 6593acea69ec8..c3cd0967a154a 100644 --- a/apps/site/util/download/constants.json +++ b/apps/site/util/download/constants.json @@ -152,7 +152,7 @@ "name": "Brew", "compatibility": { "os": ["MAC", "LINUX"], - "releases": ["Current", "Active LTS", "Maintenance LTS"] + "releases": ["Current", "LTS"] }, "url": "https://brew.sh/", "info": "layouts.download.codeBox.platformInfo.brew" @@ -213,11 +213,5 @@ "bitness": ["64", "32"], "architecture": ["arm", "x86"] }, - "statusOrder": [ - "Current", - "Active LTS", - "Maintenance LTS", - "End-of-life", - "Pending" - ] + "statusOrder": ["Current", "LTS", "End-of-life"] } From ef5592462c34ba550ef770baf20e8b372f348833 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Tue, 14 Apr 2026 14:54:55 +0100 Subject: [PATCH 2/4] Use Badges for release status in version dropdown --- .../Downloads/Release/VersionDropdown.tsx | 22 ++++++++++----- .../Common/Select/StatelessSelect/index.tsx | 28 ++++++++++++++++++- .../src/Common/Select/index.module.css | 4 +++ .../ui-components/src/Common/Select/index.tsx | 21 +++++++++++++- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/apps/site/components/Downloads/Release/VersionDropdown.tsx b/apps/site/components/Downloads/Release/VersionDropdown.tsx index fda9bb21aa6f8..cfbbd18fd0d6b 100644 --- a/apps/site/components/Downloads/Release/VersionDropdown.tsx +++ b/apps/site/components/Downloads/Release/VersionDropdown.tsx @@ -13,20 +13,27 @@ import { import type { NodeReleaseStatus } from '#site/types/releases.js'; import type { FC } from 'react'; -const getDropDownStatus = (version: string, status: NodeReleaseStatus) => { +const getDropDownStatus = (status: NodeReleaseStatus) => { if (status === 'LTS') { - return `${version} (LTS)`; + return { + label: 'LTS', + kind: 'info' as const, + }; } if (status === 'Current') { - return `${version} (Current)`; + return { + label: 'Current', + kind: 'default' as const, + }; } if (status === 'End-of-life') { - return `${version} (EoL)`; + return { + label: 'EoL', + kind: 'warning' as const, + }; } - - return version; }; const VersionDropdown: FC = () => { @@ -61,7 +68,8 @@ const VersionDropdown: FC = () => { ariaLabel={t('layouts.download.dropdown.version')} values={releases.map(({ status, versionWithPrefix }) => ({ value: versionWithPrefix, - label: getDropDownStatus(versionWithPrefix, status), + label: versionWithPrefix, + badge: getDropDownStatus(status), }))} defaultValue={release.versionWithPrefix} onChange={setVersionOrNavigate} diff --git a/packages/ui-components/src/Common/Select/StatelessSelect/index.tsx b/packages/ui-components/src/Common/Select/StatelessSelect/index.tsx index 063cb1033b7e2..af0ec212f08fe 100644 --- a/packages/ui-components/src/Common/Select/StatelessSelect/index.tsx +++ b/packages/ui-components/src/Common/Select/StatelessSelect/index.tsx @@ -2,6 +2,8 @@ import { ChevronDownIcon } from '@heroicons/react/24/solid'; import classNames from 'classnames'; import { useId, useMemo } from 'react'; +import Badge from '#ui/Common/Badge'; + import type { SelectGroup, SelectProps } from '#ui/Common/Select'; import type { LinkLike } from '#ui/types'; @@ -66,6 +68,15 @@ const StatelessSelect = ({ {currentItem.iconImage} {currentItem.label} + {currentItem.badge && ( + + {currentItem.badge.label} + + )} )} {!currentItem && ( @@ -89,7 +100,13 @@ const StatelessSelect = ({ )} {items.map( - ({ value, label, iconImage, disabled: itemDisabled }) => ( + ({ + value, + label, + iconImage, + badge, + disabled: itemDisabled, + }) => ( ({ > {iconImage} {label} + {badge && ( + + {badge.label} + + )} ) )} diff --git a/packages/ui-components/src/Common/Select/index.module.css b/packages/ui-components/src/Common/Select/index.module.css index 7909fbca3b97d..98f528ae283c9 100644 --- a/packages/ui-components/src/Common/Select/index.module.css +++ b/packages/ui-components/src/Common/Select/index.module.css @@ -161,6 +161,10 @@ dark:text-neutral-200; } +.badge { + @apply ml-auto; +} + .noscript { @apply relative cursor-pointer; diff --git a/packages/ui-components/src/Common/Select/index.tsx b/packages/ui-components/src/Common/Select/index.tsx index 3d03f8026112a..66a7fb7d6859a 100644 --- a/packages/ui-components/src/Common/Select/index.tsx +++ b/packages/ui-components/src/Common/Select/index.tsx @@ -5,6 +5,7 @@ import * as SelectPrimitive from '@radix-ui/react-select'; import classNames from 'classnames'; import { useEffect, useId, useMemo, useState } from 'react'; +import Badge, { type BadgeKind } from '#ui/Common/Badge'; import Skeleton from '#ui/Common/Skeleton'; import type { FormattedMessage, LinkLike } from '#ui/types'; @@ -18,6 +19,10 @@ export type SelectValue = { label: FormattedMessage | string; value: T; iconImage?: ReactElement; + badge?: { + label: FormattedMessage | string; + kind?: BadgeKind; + }; disabled?: boolean; }; @@ -91,7 +96,7 @@ const Select = ({ )} - {items.map(({ value, label, iconImage, disabled }) => ( + {items.map(({ value, label, iconImage, badge, disabled }) => ( ({ {iconImage} {label} + {badge && ( + + {badge.label} + + )} ))} @@ -151,6 +161,15 @@ const Select = ({ <> {currentItem.iconImage} {currentItem.label} + {currentItem.badge && ( + + {currentItem.badge.label} + + )} )} From d90307ae787c9a6dabd1a5572a9d2e71afd68e3c Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Tue, 14 Apr 2026 15:31:12 +0100 Subject: [PATCH 3/4] Improve test coverage for generateReleaseData logic --- .../generators/__tests__/releaseData.test.mjs | 179 +++++++++++++++--- 1 file changed, 153 insertions(+), 26 deletions(-) diff --git a/apps/site/next-data/generators/__tests__/releaseData.test.mjs b/apps/site/next-data/generators/__tests__/releaseData.test.mjs index 0aedbd7eaa7dd..91ad4e4de37a7 100644 --- a/apps/site/next-data/generators/__tests__/releaseData.test.mjs +++ b/apps/site/next-data/generators/__tests__/releaseData.test.mjs @@ -2,39 +2,46 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; describe('generateReleaseData', () => { - it('generates release data with correct status', async t => { - t.mock.timers.enable({ now: new Date('2024-10-18') }); + let currentNodevuData = {}; + const nodevuMock = () => Promise.resolve(currentNodevuData); + + const runWithNodevuData = async (t, now, data) => { + currentNodevuData = data; + t.mock.timers.enable({ now: new Date(now) }); t.mock.module('@nodevu/core', { - defaultExport: () => - Promise.resolve({ - 14: { - releases: { - '14.0.0': { - semver: { major: 14, raw: '14.0.0' }, - dependencies: { npm: '6.14.10', v8: '8.0.276.20' }, - releaseDate: '2021-04-20', - modules: { version: '83' }, - }, - }, - support: { - phases: { - dates: { - start: '2021-10-26', - lts: '2022-10-18', - maintenance: '2023-10-18', - end: '2024-10-18', - }, - }, - }, - }, - }), + defaultExport: nodevuMock, }); const { default: generateReleaseData } = await import('#site/next-data/generators/releaseData.mjs'); - const result = await generateReleaseData(); + return generateReleaseData(); + }; + + it('returns End-of-life when release is on or past EOL date', async t => { + const result = await runWithNodevuData(t, '2024-10-18', { + 14: { + releases: { + '14.0.0': { + semver: { major: 14, raw: '14.0.0' }, + dependencies: { npm: '6.14.10', v8: '8.0.276.20' }, + releaseDate: '2021-04-20', + modules: { version: '83' }, + }, + }, + support: { + phases: { + dates: { + start: '2021-10-26', + lts: '2022-10-18', + maintenance: '2023-10-18', + end: '2024-10-18', + }, + }, + }, + }, + }); assert.equal(result.length, 1); assert.partialDeepStrictEqual(result[0], { @@ -50,4 +57,124 @@ describe('generateReleaseData', () => { status: 'End-of-life', }); }); + + it('returns Current when release is not EOL and latest is not LTS', async t => { + const result = await runWithNodevuData(t, '2026-04-14', { + 20: { + releases: { + '20.12.0': { + semver: { major: 20, raw: '20.12.0' }, + dependencies: { npm: '10.8.2', v8: '11.3.244.8' }, + lts: { isLts: false }, + releaseDate: '2026-03-26', + modules: { version: '115' }, + }, + }, + support: { + phases: { + dates: { + start: '2025-10-22', + lts: '2026-10-22', + maintenance: '2027-10-22', + end: '2028-04-30', + }, + }, + }, + }, + }); + + assert.equal(result[0]?.status, 'Current'); + }); + + it('returns LTS when release is not EOL and latest is flagged as LTS', async t => { + const result = await runWithNodevuData(t, '2026-04-14', { + 22: { + releases: { + '22.7.0': { + semver: { major: 22, raw: '22.7.0' }, + dependencies: { npm: '10.9.0', v8: '12.4.254.10' }, + lts: { isLts: true }, + releaseDate: '2026-02-18', + modules: { version: '124' }, + }, + }, + support: { + phases: { + dates: { + start: '2026-04-23', + lts: '2026-10-21', + maintenance: '2027-10-20', + end: '2029-04-30', + }, + }, + }, + }, + }); + + assert.equal(result[0]?.status, 'LTS'); + }); + + it('returns Current when release is not EOL and LTS date has passed but latest is not LTS', async t => { + const result = await runWithNodevuData(t, '2026-04-14', { + 24: { + releases: { + '24.1.0': { + semver: { major: 24, raw: '24.1.0' }, + dependencies: { npm: '11.1.0', v8: '13.0.12.7' }, + lts: { isLts: false }, + releaseDate: '2026-03-10', + modules: { version: '130' }, + }, + }, + support: { + phases: { + dates: { + start: '2025-10-10', + lts: '2026-01-01', + maintenance: '2027-01-01', + end: '2028-10-01', + }, + }, + }, + }, + }); + + assert.equal(result[0]?.status, 'Current'); + }); + + it('uses latest and earliest release dates for releaseDate and initialDate', async t => { + const result = await runWithNodevuData(t, '2026-04-14', { + 26: { + releases: { + '26.2.0': { + semver: { major: 26, raw: '26.2.0' }, + dependencies: { npm: '11.3.1', v8: '13.2.20.1' }, + lts: { isLts: false }, + releaseDate: '2026-04-01', + modules: { version: '132' }, + }, + '26.0.0': { + semver: { major: 26, raw: '26.0.0' }, + dependencies: { npm: '11.0.0', v8: '13.1.0.0' }, + lts: { isLts: false }, + releaseDate: '2025-10-21', + modules: { version: '131' }, + }, + }, + support: { + phases: { + dates: { + start: '2025-10-21', + lts: '2026-10-20', + maintenance: '2027-10-19', + end: '2029-04-30', + }, + }, + }, + }, + }); + + assert.equal(result[0]?.releaseDate, '2026-04-01'); + assert.equal(result[0]?.initialDate, '2025-10-21'); + }); }); From 8b732c1245f5667b1f2b11e63dbdd100211e539e Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Tue, 14 Apr 2026 23:10:25 +0100 Subject: [PATCH 4/4] Consistently use EOL identifier --- .../Downloads/Release/VersionDropdown.tsx | 30 ++++--------------- .../components/EOL/EOLReleaseTable/index.tsx | 5 +--- .../PreviousReleasesTable/TableBody.tsx | 10 ++----- apps/site/components/withReleaseAlertBox.tsx | 2 +- .../generators/__tests__/releaseData.test.mjs | 4 +-- .../site/next-data/generators/releaseData.mjs | 2 +- apps/site/next.constants.mjs | 10 +++++-- apps/site/types/releases.ts | 2 +- apps/site/util/download/constants.json | 2 +- 9 files changed, 22 insertions(+), 45 deletions(-) diff --git a/apps/site/components/Downloads/Release/VersionDropdown.tsx b/apps/site/components/Downloads/Release/VersionDropdown.tsx index cfbbd18fd0d6b..516e5fcbb359e 100644 --- a/apps/site/components/Downloads/Release/VersionDropdown.tsx +++ b/apps/site/components/Downloads/Release/VersionDropdown.tsx @@ -5,37 +5,14 @@ import { useLocale, useTranslations } from 'next-intl'; import { use } from 'react'; import { redirect, usePathname } from '#site/navigation'; +import { STATUS_KIND_MAP } from '#site/next.constants.mjs'; import { ReleaseContext, ReleasesContext, } from '#site/providers/releaseProvider'; -import type { NodeReleaseStatus } from '#site/types/releases.js'; import type { FC } from 'react'; -const getDropDownStatus = (status: NodeReleaseStatus) => { - if (status === 'LTS') { - return { - label: 'LTS', - kind: 'info' as const, - }; - } - - if (status === 'Current') { - return { - label: 'Current', - kind: 'default' as const, - }; - } - - if (status === 'End-of-life') { - return { - label: 'EoL', - kind: 'warning' as const, - }; - } -}; - const VersionDropdown: FC = () => { const { releases } = use(ReleasesContext); const { release, setVersion } = use(ReleaseContext); @@ -69,7 +46,10 @@ const VersionDropdown: FC = () => { values={releases.map(({ status, versionWithPrefix }) => ({ value: versionWithPrefix, label: versionWithPrefix, - badge: getDropDownStatus(status), + badge: { + label: status, + kind: STATUS_KIND_MAP[status], + }, }))} defaultValue={release.versionWithPrefix} onChange={setVersionOrNavigate} diff --git a/apps/site/components/EOL/EOLReleaseTable/index.tsx b/apps/site/components/EOL/EOLReleaseTable/index.tsx index 9116bdf8dd5f3..bf00f75bfb6e2 100644 --- a/apps/site/components/EOL/EOLReleaseTable/index.tsx +++ b/apps/site/components/EOL/EOLReleaseTable/index.tsx @@ -3,7 +3,6 @@ import { getTranslations } from 'next-intl/server'; import provideReleaseData from '#site/next-data/providers/releaseData'; import provideVulnerabilities from '#site/next-data/providers/vulnerabilities'; -import { EOL_VERSION_IDENTIFIER } from '#site/next.constants.mjs'; import type { FC } from 'react'; @@ -15,9 +14,7 @@ const EOLReleaseTable: FC = async () => { const releaseData = await provideReleaseData(); const vulnerabilities = await provideVulnerabilities(); - const eolReleases = releaseData.filter( - release => release.status === EOL_VERSION_IDENTIFIER - ); + const eolReleases = releaseData.filter(release => release.status === 'EOL'); const t = await getTranslations(); diff --git a/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx b/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx index 742101abacaa2..eb091a59acaad 100644 --- a/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx +++ b/apps/site/components/Releases/PreviousReleasesTable/TableBody.tsx @@ -7,18 +7,13 @@ import { Fragment, useState } from 'react'; import FormattedTime from '#site/components/Common/FormattedTime'; import LinkWithArrow from '#site/components/Common/LinkWithArrow'; import Link from '#site/components/Link'; +import { STATUS_KIND_MAP } from '#site/next.constants.mjs'; import type { NodeRelease } from '#site/types'; import type { FC } from 'react'; import ReleaseModal from '../ReleaseModal'; -const BADGE_KIND_MAP = { - 'End-of-life': 'warning', - LTS: 'info', - Current: 'default', -} as const; - type PreviousReleasesTableBodyProps = { releaseData: Array; }; @@ -56,9 +51,8 @@ const PreviousReleasesTableBody: FC = ({ - + {release.status} - {release.status === 'End-of-life' ? ' (EoL)' : ''} diff --git a/apps/site/components/withReleaseAlertBox.tsx b/apps/site/components/withReleaseAlertBox.tsx index 57e20689d972a..fe57bfe24e44a 100644 --- a/apps/site/components/withReleaseAlertBox.tsx +++ b/apps/site/components/withReleaseAlertBox.tsx @@ -14,7 +14,7 @@ const WithReleaseAlertBox: FC = ({ status }) => { const t = useTranslations(); switch (status) { - case 'End-of-life': + case 'EOL': return ( { return generateReleaseData(); }; - it('returns End-of-life when release is on or past EOL date', async t => { + it('returns EOL when release is on or past EOL date', async t => { const result = await runWithNodevuData(t, '2024-10-18', { 14: { releases: { @@ -54,7 +54,7 @@ describe('generateReleaseData', () => { releaseDate: '2021-04-20', initialDate: '2021-04-20', modules: '83', - status: 'End-of-life', + status: 'EOL', }); }); diff --git a/apps/site/next-data/generators/releaseData.mjs b/apps/site/next-data/generators/releaseData.mjs index 612ba212d9ceb..c0b4c49005aae 100644 --- a/apps/site/next-data/generators/releaseData.mjs +++ b/apps/site/next-data/generators/releaseData.mjs @@ -7,7 +7,7 @@ const getNodeReleaseStatus = (latest, eol) => { const now = new Date(); if (eol && now >= new Date(eol)) { - return 'End-of-life'; + return 'EOL'; } if (latest.lts.isLts) { diff --git a/apps/site/next.constants.mjs b/apps/site/next.constants.mjs index 1a4ca677ba8bc..f621472d3c309 100644 --- a/apps/site/next.constants.mjs +++ b/apps/site/next.constants.mjs @@ -205,9 +205,15 @@ export const SEVERITY_KIND_MAP = { }; /** - * Which Node.js versions do we want to display vulnerabilities for? + * Maps Node.js version status to UI Badge kinds + * + * @type {Record} */ -export const EOL_VERSION_IDENTIFIER = 'End-of-life'; +export const STATUS_KIND_MAP = { + EOL: 'warning', + LTS: 'info', + Current: 'default', +}; /** * The location of the Node.js Security Working Group Vulnerabilities data. diff --git a/apps/site/types/releases.ts b/apps/site/types/releases.ts index 38d29bdf20469..cb2cc25fdb651 100644 --- a/apps/site/types/releases.ts +++ b/apps/site/types/releases.ts @@ -1,4 +1,4 @@ -export type NodeReleaseStatus = 'LTS' | 'Current' | 'End-of-life'; +export type NodeReleaseStatus = 'LTS' | 'Current' | 'EOL'; export type NodeReleaseSource = { major: number; diff --git a/apps/site/util/download/constants.json b/apps/site/util/download/constants.json index c3cd0967a154a..d5ccf208ccf5b 100644 --- a/apps/site/util/download/constants.json +++ b/apps/site/util/download/constants.json @@ -213,5 +213,5 @@ "bitness": ["64", "32"], "architecture": ["arm", "x86"] }, - "statusOrder": ["Current", "LTS", "End-of-life"] + "statusOrder": ["Current", "LTS", "EOL"] }