@@ -27,73 +27,73 @@ export async function downloadAndExtractTarball(
2727 const controller = new AbortController ( )
2828 const timeoutHandle = setTimeout ( ( ) => controller . abort ( ) , FETCH_TIMEOUT_MS )
2929
30- let res : Response
3130 try {
32- res = await fetch ( tarballUrl , { signal : controller . signal } )
33- } finally {
34- clearTimeout ( timeoutHandle )
35- }
36- if ( ! res . ok ) {
37- throw new Error ( `Failed to fetch tarball: ${ res . status } ${ res . statusText } ` )
38- }
39- if ( ! res . body ) {
40- throw new Error ( 'No response body from tarball fetch' )
41- }
31+ const res = await fetch ( tarballUrl , { signal : controller . signal } )
32+ if ( ! res . ok ) {
33+ throw new Error ( `Failed to fetch tarball: ${ res . status } ${ res . statusText } ` )
34+ }
35+ if ( ! res . body ) {
36+ throw new Error ( 'No response body from tarball fetch' )
37+ }
4238
43- const tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'tarball-extract-' ) )
44- try {
45- // tar rejects (preservePaths defaults to false) any entry whose path would resolve
46- // outside cwd; strict:true makes that a thrown error instead of a silent warn+skip.
47- let extractedBytes = 0
48- let extractedFiles = 0
49- const extractStream = tar . extract ( {
50- cwd : tempDir ,
51- strict : true ,
52- filter : ( _entryPath , entry ) => {
53- extractedFiles ++
54- extractedBytes += entry . size ?? 0
55- if ( extractedFiles > MAX_EXTRACTED_FILES || extractedBytes > MAX_EXTRACTED_BYTES ) {
56- ; ( extractStream as unknown as Writable ) . destroy (
57- new Error ( 'Tarball extraction exceeded size/file limits' ) ,
58- )
59- return false
60- }
61- return true
62- } ,
63- } )
39+ const tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'tarball-extract-' ) )
40+ try {
41+ // tar rejects (preservePaths defaults to false) any entry whose path would resolve
42+ // outside cwd; strict:true makes that a thrown error instead of a silent warn+skip.
43+ let extractedBytes = 0
44+ let extractedFiles = 0
45+ const extractStream = tar . extract ( {
46+ cwd : tempDir ,
47+ strict : true ,
48+ filter : ( _entryPath , entry ) => {
49+ extractedFiles ++
50+ extractedBytes += entry . size ?? 0
51+ if ( extractedFiles > MAX_EXTRACTED_FILES || extractedBytes > MAX_EXTRACTED_BYTES ) {
52+ ; ( extractStream as unknown as Writable ) . destroy (
53+ new Error ( 'Tarball extraction exceeded size/file limits' ) ,
54+ )
55+ return false
56+ }
57+ return true
58+ } ,
59+ } )
6460
65- let downloadedBytes = 0
66- const downloadLimiter = new Transform ( {
67- transform ( chunk , _encoding , callback ) {
68- downloadedBytes += chunk . length
69- if ( downloadedBytes > MAX_DOWNLOAD_BYTES ) {
70- callback ( new Error ( 'Tarball download exceeded size limit' ) )
71- return
72- }
73- callback ( null , chunk )
74- } ,
75- } )
61+ let downloadedBytes = 0
62+ const downloadLimiter = new Transform ( {
63+ transform ( chunk , _encoding , callback ) {
64+ downloadedBytes += chunk . length
65+ if ( downloadedBytes > MAX_DOWNLOAD_BYTES ) {
66+ callback ( new Error ( 'Tarball download exceeded size limit' ) )
67+ return
68+ }
69+ callback ( null , chunk )
70+ } ,
71+ } )
7672
77- await new Promise < void > ( ( resolve , reject ) => {
78- Readable . fromWeb ( res . body as unknown as NodeWebReadableStream < Uint8Array > )
79- . on ( 'error' , reject )
80- . pipe ( downloadLimiter )
81- . on ( 'error' , reject )
82- . pipe ( extractStream as unknown as NodeJS . WritableStream )
83- . on ( 'finish' , resolve )
84- . on ( 'error' , reject )
85- } )
73+ await new Promise < void > ( ( resolve , reject ) => {
74+ Readable . fromWeb ( res . body as unknown as NodeWebReadableStream < Uint8Array > )
75+ . on ( 'error' , reject )
76+ . pipe ( downloadLimiter )
77+ . on ( 'error' , reject )
78+ . pipe ( extractStream as unknown as NodeJS . WritableStream )
79+ . on ( 'finish' , resolve )
80+ . on ( 'error' , reject )
81+ } )
8682
87- const items = fs . readdirSync ( tempDir )
88- const commonPrefix =
89- items . length === 1 && fs . statSync ( path . join ( tempDir , items [ 0 ] ) ) . isDirectory ( )
90- ? items [ 0 ]
91- : null
92- const srcBase = commonPrefix ? path . join ( tempDir , commonPrefix ) : tempDir
83+ const items = fs . readdirSync ( tempDir )
84+ const commonPrefix =
85+ items . length === 1 && fs . statSync ( path . join ( tempDir , items [ 0 ] ) ) . isDirectory ( )
86+ ? items [ 0 ]
87+ : null
88+ const srcBase = commonPrefix ? path . join ( tempDir , commonPrefix ) : tempDir
9389
94- copyTreeGuarded ( srcBase , destDir )
95- } finally {
96- fs . rmSync ( tempDir , { recursive : true , force : true } )
90+ copyTreeGuarded ( srcBase , destDir )
91+ } finally {
92+ fs . rmSync ( tempDir , { recursive : true , force : true } )
93+ }
94+ } catch ( err ) {
95+ clearTimeout ( timeoutHandle )
96+ throw err
9797 }
9898}
9999
0 commit comments