diff --git a/src/interfaces/types.d.ts b/src/interfaces/types.d.ts index 99e09c2e..9e9a16ee 100644 --- a/src/interfaces/types.d.ts +++ b/src/interfaces/types.d.ts @@ -18,9 +18,15 @@ interface PkgSize { disabled?: boolean; } +interface ApiResponse { + publishSize: number; + installSize: number; +} + interface ResultProps { pkgSize: PkgSize; readings: PkgSize[]; + cacheResult: boolean; } interface ParsedUrlQuery { diff --git a/src/page-props/results.ts b/src/page-props/results.ts index bb463347..c56fca47 100644 --- a/src/page-props/results.ts +++ b/src/page-props/results.ts @@ -10,63 +10,66 @@ import { calculatePackageSize } from '../util/backend/npm-stats'; import { versionUnknown } from '../util/constants'; export async function getResultProps(query: ParsedUrlQuery, tmp: string) { - if (query && typeof query.p === 'string') { - let { name, version } = parsePackageString(query.p); - let manifest: NpmManifest; - try { - manifest = await fetchManifest(name); - } catch (e) { - console.error(`Package ${name} does not exist in npm`); - return packageNotFound(name); - } - - if (!version) { - version = await getLatestVersion(manifest); - console.log(`Querystring missing version, using version ${name}@${version}`); - } + if (!query || typeof query.p !== 'string') { + throw new Error(`Unknown query string ${query}`); + } + let { name, version } = parsePackageString(query.p); + let manifest: NpmManifest; + let cacheResult = true; - const allVersions = getAllVersions(manifest); - if (!allVersions.includes(version)) { - console.error(`Version ${name}@${version} does not exist in npm`); - return packageNotFound(name); - } + try { + manifest = await fetchManifest(name); + } catch (e) { + console.error(`Package ${name} does not exist in npm`); + return packageNotFound(name); + } - const filteredVersions = isFullRelease(version) - ? allVersions.filter(isFullRelease) - : allVersions; - const chartVersions = getVersionsForChart(filteredVersions, version, 7); + if (!version) { + version = await getLatestVersion(manifest); + cacheResult = false; + console.log(`Querystring missing version, using version ${name}@${version}`); + } - let existing = await findOne(name, version); - if (!existing) { - console.log(`Cache miss for ${name}@${version} - running npm install...`); - const start = new Date(); - existing = await calculatePackageSize(name, version, tmp); - const end = new Date(); - const sec = (end.getTime() - start.getTime()) / 1000; - console.log(`Calculated size of ${name}@${version} in ${sec}s`); - insert(existing); - } + const allVersions = getAllVersions(manifest); + if (!allVersions.includes(version)) { + console.error(`Version ${name}@${version} does not exist in npm`); + return packageNotFound(name); + } - const cachedVersions = await findAll(name); + const filteredVersions = isFullRelease(version) + ? allVersions.filter(isFullRelease) + : allVersions; + const chartVersions = getVersionsForChart(filteredVersions, version, 7); - const readings = chartVersions.map(v => { - if (v in cachedVersions) { - return cachedVersions[v]; - } else { - return { - name: name, - version: v, - publishSize: 0, - installSize: 0, - disabled: true, - }; - } - }); - const result: ResultProps = { pkgSize: existing, readings }; - return result; + let existing = await findOne(name, version); + if (!existing) { + console.log(`Cache miss for ${name}@${version} - running npm install...`); + const start = new Date(); + existing = await calculatePackageSize(name, version, tmp); + const end = new Date(); + const sec = (end.getTime() - start.getTime()) / 1000; + console.log(`Calculated size of ${name}@${version} in ${sec}s`); + insert(existing); } - throw new Error(`Unknown query string ${query}`); + const cachedVersions = await findAll(name); + + const readings = chartVersions.map(v => { + if (v in cachedVersions) { + return cachedVersions[v]; + } else { + return { + name: name, + version: v, + publishSize: 0, + installSize: 0, + disabled: true, + }; + } + }); + + const result: ResultProps = { pkgSize: existing, readings, cacheResult }; + return result; } function packageNotFound(name: string) { @@ -77,6 +80,6 @@ function packageNotFound(name: string) { installSize: 0, disabled: true, }; - const result: ResultProps = { pkgSize, readings: [] }; + const result: ResultProps = { pkgSize, readings: [], cacheResult: false }; return result; } diff --git a/src/server.ts b/src/server.ts index 7649424c..31b077df 100644 --- a/src/server.ts +++ b/src/server.ts @@ -4,7 +4,7 @@ import { createReadStream } from 'fs'; import { mimeType, cacheControl } from './util/backend/lookup'; import { renderPage } from './pages/_document'; -import { browserUrl, browserMapUrl, pages } from './util/constants'; +import { browserUrl, browserMapUrl, pages, versionUnknown } from './util/constants'; import { getResultProps } from './page-props/results'; import { getBadgeUrl } from './util/badge'; @@ -25,11 +25,20 @@ createServer(async (req, res) => { res.setHeader('Cache-Control', cacheControl(isProd, 7)); createReadStream(`./dist${pathname}`).pipe(res); } else if (pathname === pages.badge) { - const resultProps = await getResultProps(query, TMPDIR); - const badgeUrl = getBadgeUrl(resultProps.pkgSize); + const { pkgSize, cacheResult } = await getResultProps(query, TMPDIR); + const badgeUrl = getBadgeUrl(pkgSize); res.statusCode = 302; res.setHeader('Location', badgeUrl); + res.setHeader('Cache-Control', cacheControl(isProd, cacheResult ? 7 : 0)); res.end(); + } else if (pathname === pages.api_json) { + const { pkgSize, cacheResult } = await getResultProps(query, TMPDIR); + const { publishSize, installSize, version } = pkgSize; + const result: ApiResponse = { publishSize, installSize }; + res.statusCode = version === versionUnknown ? 404 : 200; + res.setHeader('Content-Type', mimeType(pathname)); + res.setHeader('Cache-Control', cacheControl(isProd, cacheResult ? 7 : 0)); + res.end(JSON.stringify(result)); } else { res.setHeader('Content-Type', mimeType('*.html')); res.setHeader('Cache-Control', cacheControl(isProd, 0)); diff --git a/src/util/constants.ts b/src/util/constants.ts index 16b8a0b8..3a45fa52 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -9,6 +9,7 @@ export const pages = { index: '/index', result: '/result', badge: '/badge', + api_json: '/api.json', }; export const containerId = 'app-container';