Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

always show the latest version of nvm #7296

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions apps/site/app/[locale]/next-data/nvm-data/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import provideNvmData from '@/next-data/providers/nvmData';
import { defaultLocale } from '@/next.locales.mjs';

// This is the Route Handler for the `GET` method which handles the request
// for generating static data for the latest nvm version
// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers
export const GET = async () => {
const nvmData = provideNvmData();

return Response.json(nvmData);
};

// This function generates the static paths that come from the dynamic segments
// `[locale]/next-data/nvm-data/` and returns an array of all available static paths
// This is used for ISR static validation and generation
export const generateStaticParams = async () => [
{ locale: defaultLocale.code },
];

// Enforces that only the paths from `generateStaticParams` are allowed, giving 404 on the contrary
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
export const dynamicParams = false;

// Enforces that this route is used as static rendering
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'error';

// Ensures that this endpoint is invalidated and re-executed every X minutes
// so that when new deployments happen, the data is refreshed
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
export const revalidate = 300;
21 changes: 14 additions & 7 deletions apps/site/components/Downloads/Release/ReleaseCodeBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,20 @@ const ReleaseCodeBox: FC = () => {
const t = useTranslations();

useEffect(() => {
const updatedCode = getNodeDownloadSnippet(release, os, t)[platform];
// Docker and NVM support downloading tags/versions by their full release number
// but usually we should recommend users to download "major" versions
// since our Download Buttons get the latest minor of a major, it does make sense
// to request installation of a major via a package manager
memoizedShiki.then(shiki => shiki(updatedCode, 'bash')).then(setCode);
// Only react when the specific release number changed
async function getSnippet() {
const [shiki, { [platform]: updatedCode }] = await Promise.all([
memoizedShiki,
getNodeDownloadSnippet(release, os, t),
]);

// Docker and nvm support downloading tags/versions by their full release number
// but usually we should recommend users to download "major" versions since
// our Download Buttons get the latest minor of a major, it does make sense
// to request installation of a major via a package manager
setCode(await shiki(updatedCode, 'bash'));
// Only react when the specific release number changed
ljharb marked this conversation as resolved.
Show resolved Hide resolved
}
getSnippet();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [release.versionWithPrefix, os, platform]);

Expand Down
24 changes: 24 additions & 0 deletions apps/site/next-data/generators/nvmData.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

const latestKnownVersion = 'v0.40.1';

/**
* Fetches the latest NVM version
* @returns {Promise<`v${string}`>} Latest NVM version
*/
export default async function generateNvmData() {
return fetch('https://latest.nvm.sh', { redirect: 'manual' })
.then(({ headers }) => {
const url = headers.get('location');
ovflowd marked this conversation as resolved.
Show resolved Hide resolved
if (!url) {
throw new Error('No redirect location found');
}
return fetch(url, { redirect: 'manual' });
})
.then(x => {
const url = x.headers.get('location');
const version = url?.slice(url.lastIndexOf('/') + 1);
return version || latestKnownVersion;
})
.catch(() => latestKnownVersion);
}
17 changes: 17 additions & 0 deletions apps/site/next-data/nvmData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
ENABLE_STATIC_EXPORT,
IS_DEVELOPMENT,
NEXT_DATA_URL,
VERCEL_ENV,
} from '@/next.constants.mjs';

export default async function getNvmData(): Promise<`v${string}`> {
if (ENABLE_STATIC_EXPORT || (!IS_DEVELOPMENT && !VERCEL_ENV)) {
const { default: provideNvmData } = await import(
'@/next-data/providers/nvmData'
);
provideNvmData();
}

return fetch(`${NEXT_DATA_URL}nvm-data`).then(r => r.json());
}
7 changes: 7 additions & 0 deletions apps/site/next-data/providers/nvmData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { cache } from 'react';

import generateNvmData from '@/next-data/generators/nvmData.mjs';

const nvmData = await generateNvmData();

export default cache(() => nvmData);
9 changes: 5 additions & 4 deletions apps/site/util/getNodeDownloadSnippet.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import dedent from 'dedent';
import type { TranslationValues } from 'next-intl';

import getNvmData from '@/next-data/nvmData';
import type { NodeRelease } from '@/types';
import type { PackageManager } from '@/types/release';
import type { UserOS } from '@/types/userOS';

export const getNodeDownloadSnippet = (
export async function getNodeDownloadSnippet(
release: NodeRelease,
os: UserOS,
t: (key: string, values?: TranslationValues) => string
) => {
) {
const snippets: Record<PackageManager, string> = {
NVM: '',
FNM: '',
Expand Down Expand Up @@ -39,7 +40,7 @@ export const getNodeDownloadSnippet = (
if (os === 'MAC' || os === 'LINUX') {
snippets.NVM = dedent`
# ${t('layouts.download.codeBox.installsNvm')}
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${await getNvmData()}/install.sh | bash

# ${t('layouts.download.codeBox.downloadAndInstallNodejsRestartTerminal')}
nvm install ${release.major}
Expand Down Expand Up @@ -118,4 +119,4 @@ export const getNodeDownloadSnippet = (
}

return snippets;
};
}
Loading