File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -258,6 +258,23 @@ describe('readOrgManifest', () => {
258258 expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
259259 } ) ;
260260
261+ it ( 'treats a tarball probe failure as "no manifest" so passthrough still works' , async ( ) => {
262+ // A normal @scope /create package (no manifest anywhere) whose tarball
263+ // cannot be probed — e.g. a download error — must not turn into a hard
264+ // failure; `null` lets the caller fall through to the passthrough path.
265+ vi . spyOn ( globalThis , 'fetch' ) . mockImplementation ( async ( input ) => {
266+ const url = typeof input === 'string' ? input : input instanceof URL ? input . href : input . url ;
267+ if ( url . endsWith ( '.tgz' ) ) {
268+ throw new Error ( 'network unreachable' ) ;
269+ }
270+ return new Response (
271+ JSON . stringify ( packument ( undefined , { dist : { tarball : TARBALL_URL } } ) ) ,
272+ { status : 200 } ,
273+ ) ;
274+ } ) ;
275+ expect ( await readOrgManifest ( '@your-org' ) ) . toBeNull ( ) ;
276+ } ) ;
277+
261278 it ( 'returns null when createConfig.templates is an empty array' , async ( ) => {
262279 mockFetchJson ( packument ( [ ] ) ) ;
263280 expect ( await readOrgManifest ( '@your-org' ) ) . toBeNull ( ) ;
Original file line number Diff line number Diff line change @@ -339,10 +339,22 @@ export async function readOrgManifest(
339339 }
340340 let templates = validateManifest ( meta , packageName ) ;
341341 if ( ! templates && meta . createConfig === undefined && meta . dist ?. tarball ) {
342- // `createConfig` absent (not merely empty) → the registry stripped it from
343- // the version metadata; recover it from the published tarball. See
342+ // `createConfig` absent (not merely empty) → either the registry stripped
343+ // it from the version metadata, or the package simply has no manifest.
344+ // Probe the published tarball to tell the two apart. See
344345 // `readPackageJsonFromTarball` for the full rationale.
345- const packageJson = await readPackageJsonFromTarball ( meta . dist . tarball , meta . dist . integrity ) ;
346+ //
347+ // The probe is best-effort: a download/size/integrity/parse failure must
348+ // not block normal `@scope/create` packages that never had a manifest
349+ // from reaching the passthrough path, so it degrades to "no manifest".
350+ // A manifest that IS present but malformed still throws below —
351+ // `validateManifest` runs outside the try so schema errors stay loud.
352+ let packageJson : unknown = null ;
353+ try {
354+ packageJson = await readPackageJsonFromTarball ( meta . dist . tarball , meta . dist . integrity ) ;
355+ } catch {
356+ packageJson = null ;
357+ }
346358 templates = validateManifest ( packageJson , packageName ) ;
347359 }
348360 if ( ! templates ) {
You can’t perform that action at this time.
0 commit comments