1- import { Bun , getPackageApi , getPackageJson , getPackageTypes } from "@jsdocs-io/extractor" ;
1+ import {
2+ Bun ,
3+ getPackageApi ,
4+ getPackageJson ,
5+ getPackageTypes ,
6+ type PackageApi ,
7+ } from "@jsdocs-io/extractor" ;
28import { goTry } from "go-go-try" ;
39import { join } from "pathe" ;
10+ import type { NormalizedPackageJson } from "read-pkg" ;
411import { PackageApiMemDb } from "../../db/package-api-mem-db" ;
512import { PackageApiR2Bucket } from "../../db/package-api-r2-bucket" ;
613import { serverEnv } from "../../server-env" ;
@@ -10,15 +17,40 @@ import { packageId } from "../../utils/package-id";
1017import { resolvePackage } from "../../utils/resolve-package" ;
1118import { tempDir } from "../../utils/temp-dir" ;
1219import { getLogger } from "../get-logger" ;
13- import { redirect } from "../redirect" ;
1420import { parsePackageSlug } from "./parse-package-slug" ;
1521
1622const bun = new Bun ( serverEnv . BUN_PATH ) ;
1723const db = serverEnv . CF_BUCKET_NAME ? new PackageApiR2Bucket ( ) : new PackageApiMemDb ( ) ;
1824
19- export interface HandlePackageOutput { }
25+ export interface PackageInfo {
26+ pkgId : string ;
27+ subpath : string ;
28+ pkgJson : NormalizedPackageJson ;
29+ generatedAt : string ;
30+ generatedIn : number ;
31+ }
32+
33+ export interface PackageInfoWithDtPackage extends PackageInfo {
34+ dtPkgName : string ;
35+ }
36+
37+ export interface PackageInfoWithApi extends PackageInfo {
38+ pkgApi : PackageApi ;
39+ }
2040
21- export async function handlePackage ( slug : string ) {
41+ export type HandlePackageOutput =
42+ | { status : "bad-request" }
43+ | { status : "not-found" }
44+ | { status : "found" ; path : string }
45+ | { status : "error" }
46+ | { status : "pkg-has-invalid-license" ; pkgInfo : PackageInfo }
47+ | { status : "pkg-is-deprecated-dt-pkg" ; pkgInfo : PackageInfo }
48+ | { status : "pkg-has-no-types" ; pkgInfo : PackageInfo }
49+ | { status : "pkg-has-dt-pkg" ; pkgInfo : PackageInfoWithDtPackage }
50+ | { status : "pkg-has-api" ; pkgInfo : PackageInfoWithApi }
51+ | { status : "pkg-has-no-api" ; pkgInfo : PackageInfo } ;
52+
53+ export async function handlePackage ( slug : string ) : Promise < HandlePackageOutput > {
2254 const log = getLogger ( "handlePackage" ) ;
2355 log . info ( { path : `/package/${ slug } ` } ) ;
2456
@@ -29,7 +61,7 @@ export async function handlePackage(slug: string) {
2961 const [ slugErr , slugOut ] = goTry ( ( ) => parsePackageSlug ( slug ) ) ;
3062 if ( slugErr !== undefined ) {
3163 log . error ( { err : slugErr } ) ;
32- return redirect ( "/404" ) ;
64+ return { status : "bad-request" } ;
3365 }
3466 const { pkg, pkgName, subpath } = slugOut ;
3567
@@ -42,53 +74,57 @@ export async function handlePackage(slug: string) {
4274 const [ bunErr , packages ] = await goTry ( bun . add ( pkg , cwd ) ) ;
4375 if ( bunErr !== undefined ) {
4476 log . error ( { err : bunErr } ) ;
45- return redirect ( "/404" ) ;
77+ return { status : "not-found" } ;
4678 }
4779
4880 // Redirect to the canonical package page if necessary.
4981 const resolvedPkg = resolvePackage ( pkgName , packages ) ;
5082 const pkgId = packageId ( resolvedPkg , subpath ) ;
5183 if ( pkg !== resolvedPkg ) {
5284 log . info ( { redirect : `${ pkg } -> ${ resolvedPkg } ` } ) ;
53- return redirect ( `/package/${ pkgId } ` ) ;
85+ return { status : "found" , path : `/package/${ pkgId } ` } ;
5486 }
5587
5688 // Read the package's own `package.json`.
5789 const pkgDir = join ( cwd , "node_modules" , pkgName ) ;
5890 const [ pkgJsonErr , pkgJson ] = await goTry ( getPackageJson ( pkgDir ) ) ;
5991 if ( pkgJsonErr !== undefined ) {
6092 log . error ( { err : pkgJsonErr } ) ;
61- return redirect ( "/500" ) ;
93+ return { status : "error" } ;
6294 }
6395
6496 // Check if the package has an SPDX license.
6597 const [ licenseErr ] = goTry ( ( ) => checkLicense ( pkgJson . license ) ) ;
6698 if ( licenseErr !== undefined ) {
6799 log . warn ( { warn : licenseErr } ) ;
68100 return {
69- status : "pkg-has-invalid-license" as const ,
70- pkgId,
71- subpath,
72- pkgJson,
73- generatedAt : generatedAt ( ) ,
74- generatedIn : generatedIn ( start ) ,
101+ status : "pkg-has-invalid-license" ,
102+ pkgInfo : {
103+ pkgId,
104+ subpath,
105+ pkgJson,
106+ generatedAt : generatedAt ( ) ,
107+ generatedIn : generatedIn ( start ) ,
108+ } ,
75109 } ;
76110 }
77111
78112 // Check if the package provides type definitions and if not
79113 // check if there is a corresponding DefinitelyTyped (DT) package.
80- const types = getPackageTypes ( { pkgJson, subpath } ) ;
81- if ( ! types ) {
114+ const [ typesErr , types ] = goTry ( ( ) => getPackageTypes ( { pkgJson, subpath } ) ) ;
115+ if ( typesErr !== undefined || ! types ) {
82116 // A DT package without types is deprecated.
83117 if ( isDTPackage ( pkgName ) ) {
84118 log . warn ( { warn : "deprecated DT package" } ) ;
85119 return {
86- status : "pkg-is-deprecated-dt-pkg" as const ,
87- pkgId,
88- subpath,
89- pkgJson,
90- generatedAt : generatedAt ( ) ,
91- generatedIn : generatedIn ( start ) ,
120+ status : "pkg-is-deprecated-dt-pkg" ,
121+ pkgInfo : {
122+ pkgId,
123+ subpath,
124+ pkgJson,
125+ generatedAt : generatedAt ( ) ,
126+ generatedIn : generatedIn ( start ) ,
127+ } ,
92128 } ;
93129 }
94130
@@ -98,24 +134,28 @@ export async function handlePackage(slug: string) {
98134 if ( bunErr !== undefined ) {
99135 log . warn ( { warn : "no DT package" } ) ;
100136 return {
101- status : "pkg-has-no-types" as const ,
102- pkgId,
103- subpath,
104- pkgJson,
105- generatedAt : generatedAt ( ) ,
106- generatedIn : generatedIn ( start ) ,
137+ status : "pkg-has-no-types" ,
138+ pkgInfo : {
139+ pkgId,
140+ subpath,
141+ pkgJson,
142+ generatedAt : generatedAt ( ) ,
143+ generatedIn : generatedIn ( start ) ,
144+ } ,
107145 } ;
108146 }
109147
110148 // A DT package exists.
111149 return {
112- status : "pkg-has-dt-pkg" as const ,
113- pkgId,
114- subpath,
115- pkgJson,
116- dtPkgName,
117- generatedAt : generatedAt ( ) ,
118- generatedIn : generatedIn ( start ) ,
150+ status : "pkg-has-dt-pkg" ,
151+ pkgInfo : {
152+ pkgId,
153+ subpath,
154+ pkgJson,
155+ dtPkgName,
156+ generatedAt : generatedAt ( ) ,
157+ generatedIn : generatedIn ( start ) ,
158+ } ,
119159 } ;
120160 }
121161
@@ -127,13 +167,15 @@ export async function handlePackage(slug: string) {
127167 if ( dbPkgApi ) {
128168 log . info ( { db : db . dbName , pkgId, getPkgApi : true } ) ;
129169 return {
130- status : "pkg-has-api" as const ,
131- pkgId,
132- subpath,
133- pkgJson,
134- pkgApi : dbPkgApi ,
135- generatedAt : generatedAt ( ) ,
136- generatedIn : generatedIn ( start ) ,
170+ status : "pkg-has-api" ,
171+ pkgInfo : {
172+ pkgId,
173+ subpath,
174+ pkgJson,
175+ pkgApi : dbPkgApi ,
176+ generatedAt : generatedAt ( ) ,
177+ generatedIn : generatedIn ( start ) ,
178+ } ,
137179 } ;
138180 }
139181
@@ -143,11 +185,13 @@ export async function handlePackage(slug: string) {
143185 log . error ( { err : pkgApiErr } ) ;
144186 return {
145187 status : "pkg-has-no-api" as const ,
146- pkgId,
147- subpath,
148- pkgJson,
149- generatedAt : generatedAt ( ) ,
150- generatedIn : generatedIn ( start ) ,
188+ pkgInfo : {
189+ pkgId,
190+ subpath,
191+ pkgJson,
192+ generatedAt : generatedAt ( ) ,
193+ generatedIn : generatedIn ( start ) ,
194+ } ,
151195 } ;
152196 }
153197
@@ -162,12 +206,14 @@ export async function handlePackage(slug: string) {
162206 // Return data for rendering.
163207 return {
164208 status : "pkg-has-api" as const ,
165- pkgId,
166- subpath,
167- pkgJson,
168- pkgApi,
169- generatedAt : generatedAt ( ) ,
170- generatedIn : generatedIn ( start ) ,
209+ pkgInfo : {
210+ pkgId,
211+ subpath,
212+ pkgJson,
213+ pkgApi,
214+ generatedAt : generatedAt ( ) ,
215+ generatedIn : generatedIn ( start ) ,
216+ } ,
171217 } ;
172218}
173219
0 commit comments