Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ yarn-error.log*
apps/frontpage/content/docs
apps/frontpage/content/snippets
apps/frontpage/generated-redirects.json
apps/frontpage/generated-versions.json
apps/frontpage/public/docs-assets

# ui
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ This project is structured around [Turborepo](https://turbo.build/repo). This do

> Generate redirects file

#### `npx turbo generate-versions`

> Generate Storybook version metadata from npm dist-tags

#### `npx turbo dev`

> Run all apps locally
Expand Down
30 changes: 2 additions & 28 deletions apps/frontpage/app/versions/route.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import crypto from 'node:crypto';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { headers } from 'next/headers';
import type { NextRequest } from 'next/server';
import { BigQuery } from '@google-cloud/bigquery';
import { parse as semverParse } from 'semver';
import { latestVersion } from '@repo/utils';
import { readGeneratedVersions } from '../../lib/generated-versions';

// eslint-disable-next-line no-useless-escape, prefer-named-capture-group -- Escape is absolutely necessary for regex?
const SEP_REGEX = /([\.:])/;
Expand All @@ -15,13 +13,6 @@ const logger = { log: (..._msgs: unknown[]) => {} };

const { GCP_CREDENTIALS, SKIP_IP_HASH } = process.env;

const versionFilesDir = path.join(
process.cwd(),
'content/docs',
latestVersion.id,
'versions',
);

const md5 = (host: string) => {
const hash = crypto.createHash('md5');
hash.update(host);
Expand Down Expand Up @@ -99,27 +90,10 @@ const log = async (searchParams: URLSearchParams) => {
await table.insert([row]);
};

type DistTag = 'latest' | 'next';

const versions = async () => {
logger.log('fetching versions');

async function getVersionData(distTag: DistTag) {
const data = JSON.parse(
await readFile(
new URL(path.join(versionFilesDir, `${distTag}.json`), import.meta.url),
'utf8',
),
);
// Strip off no-longer-used `info` property
const { version } = data as { version: string };
return { version };
}

const latest = await getVersionData('latest');
const next = await getVersionData('next');

return JSON.stringify({ latest, next });
return JSON.stringify(await readGeneratedVersions());
};

export async function GET(request: NextRequest) {
Expand Down
79 changes: 79 additions & 0 deletions apps/frontpage/lib/generated-versions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import path from 'node:path';
import { readFile, writeFile } from 'node:fs/promises';
import { valid as isValidSemver } from 'semver';

export interface GeneratedVersion {
version: string;
}

export interface GeneratedVersions {
latest: GeneratedVersion;
next: GeneratedVersion;
}

const DIST_TAGS_URL =
'https://registry.npmjs.org/-/package/storybook/dist-tags';

export const generatedVersionsFilePath = path.join(
process.cwd(),
'generated-versions.json',
);

function assertDistTagVersion(
distTag: keyof GeneratedVersions,
version: unknown,
): GeneratedVersion {
if (typeof version !== 'string' || !isValidSemver(version)) {
throw new Error(
`Expected a valid semver string for the ${distTag} dist-tag, received ${JSON.stringify(version)}`,
);
}

return { version };
}

export async function fetchGeneratedVersions(): Promise<GeneratedVersions> {
const response = await fetch(DIST_TAGS_URL, {
headers: {
Accept: 'application/json',
'Cache-Control': 'no-cache',
},
});

if (!response.ok) {
throw new Error(
`Failed to fetch Storybook dist-tags from npm: ${String(response.status)} ${response.statusText}`,
);
}

const distTags = (await response.json()) as Partial<
Record<keyof GeneratedVersions, unknown>
>;

return {
latest: assertDistTagVersion('latest', distTags.latest),
next: assertDistTagVersion('next', distTags.next),
};
}

export async function readGeneratedVersions(): Promise<GeneratedVersions> {
const fileContents = await readFile(generatedVersionsFilePath, 'utf8');
const parsed = JSON.parse(fileContents) as Partial<
Record<keyof GeneratedVersions, { version?: unknown }>
>;

return {
latest: assertDistTagVersion('latest', parsed.latest?.version),
next: assertDistTagVersion('next', parsed.next?.version),
};
}

export async function writeGeneratedVersions(
versions: GeneratedVersions,
): Promise<void> {
await writeFile(
generatedVersionsFilePath,
`${JSON.stringify(versions, null, 2)}\n`,
'utf8',
);
}
1 change: 1 addition & 0 deletions apps/frontpage/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ module.exports = withBundleAnalyzer(
*/
outputFileTracingIncludes: {
'/docs/**': ['./content/docs/**'],
'/versions': ['./generated-versions.json'],
},
},
async redirects() {
Expand Down
1 change: 1 addition & 0 deletions apps/frontpage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"lint": "next lint",
"typecheck": "tsc --noEmit",
"fetch-docs": "tsx --tsconfig tsconfig.json scripts/get-local-docs.ts",
"generate-versions": "tsx --tsconfig tsconfig.json scripts/generate-versions.ts",
"generate-redirects": "tsx --tsconfig tsconfig.json scripts/generate-redirects.ts",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
"storybook": "storybook dev -p 6006",
Expand Down
11 changes: 11 additions & 0 deletions apps/frontpage/scripts/generate-versions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {
fetchGeneratedVersions,
writeGeneratedVersions,
} from '../lib/generated-versions';

async function generate(): Promise<void> {
const versions = await fetchGeneratedVersions();
await writeGeneratedVersions(versions);
}

void generate();
7 changes: 6 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
"outputs": ["./apps/frontpage/generated-redirects.json"],
"cache": false
},
"generate-versions": {
"cache": false,
"outputs": ["./apps/frontpage/generated-versions.json"]
},
"fetch-docs": {
"cache": false
},
Expand All @@ -41,7 +45,7 @@
"inputs": ["$TURBO_DEFAULT$", ".env"]
},
"build": {
"dependsOn": ["fetch-docs", "generate-redirects", "^build"],
"dependsOn": ["fetch-docs", "generate-redirects", "generate-versions", "^build"],
"outputs": [
"dist/**",
".next/**",
Expand All @@ -51,6 +55,7 @@
"inputs": [
"$TURBO_DEFAULT$",
".env",
"./apps/frontpage/generated-versions.json",
"./apps/frontpage/content/docs/**",
"./apps/frontpage/content/snippets/**",
"./apps/frontpage/public/docs-assets/**"
Expand Down
Loading