diff --git a/README.md b/README.md index 8a8ecaf..d2973be 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ $ npm install -g @hyperplay/cli $ hyperplay COMMAND running command... $ hyperplay (--version) -@hyperplay/cli/2.14.9 darwin-arm64 node-v22.11.0 +@hyperplay/cli/2.14.10 darwin-arm64 node-v22.11.0 $ hyperplay --help [COMMAND] USAGE $ hyperplay COMMAND diff --git a/package-lock.json b/package-lock.json index baea0f2..7629148 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@hyperplay/cli", - "version": "2.14.3", + "version": "2.14.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@hyperplay/cli", - "version": "2.14.3", + "version": "2.14.10", "license": "MPL-2.0", "dependencies": { "@oclif/core": "^1.8.0", @@ -17109,4 +17109,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 9b1951e..05dbc90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperplay/cli", - "version": "2.14.9", + "version": "2.14.10", "description": "Hyperplay CLI", "author": "HyperPlay Labs, Inc.", "bin": { diff --git a/src/releases.ts b/src/releases.ts index 8096e22..83e12cc 100644 --- a/src/releases.ts +++ b/src/releases.ts @@ -89,25 +89,36 @@ export async function uploadRelease(client: AxiosInstance, config: ReleaseConfig if (!fileData) throw new Error(`File data not found for ${url.fileName}`); const fileType = mime.lookup(fileData) || 'application/octet-stream'; - const progressIterator = uploadFileS3( - fs.createReadStream(fileData), - url.uploadId, - url.key, - url.partUrls, - fileType, - { client } - ); + const fileStream = fs.createReadStream(fileData); + fileStream.setMaxListeners(20); let location = ''; - for await (const progressUpdate of progressIterator) { - if (typeof progressUpdate === 'number') { - CliUx.ux.log(`Upload progress for ${platformKey} - ${url.fileName}: ${progressUpdate}%`); - } else { - location = progressUpdate; + try { + const progressIterator = uploadFileS3( + fileStream, + url.uploadId, + url.key, + url.partUrls, + fileType, + { client } + ); + + for await (const progressUpdate of progressIterator) { + if (typeof progressUpdate === 'number') { + CliUx.ux.log(`Upload progress for ${platformKey} - ${url.fileName}: ${progressUpdate}%`); + } else { + location = progressUpdate; + } } - } - if (!location) throw new Error('No location returned after upload'); + if (!location) throw new Error('No location returned after upload'); + } catch (error) { + // Ensure the stream is properly closed on error + if (!fileStream.destroyed) { + fileStream.destroy(); + } + throw error; + } const fileStat = await fs.promises.stat(fileData); const downloadSize = fileStat.size.toString(); diff --git a/src/zip.ts b/src/zip.ts index e7a15ad..0bc8063 100644 --- a/src/zip.ts +++ b/src/zip.ts @@ -9,31 +9,55 @@ export function zipDirectory(sourceDir: string, outPath: string): Promise zlib: { level: 9 } }); - archive.on('progress', (progress)=>{ + // Use function references for easier cleanup + const onProgress = (progress: { entries: { processed: number; total: number }; fs: { processedBytes: number; totalBytes: number } }) => { let progressString = `Zip Progress: Entries ${progress.entries.processed} out of ${progress.entries.total}.`; progressString += ` Bytes ${progress.fs.processedBytes} out of ${progress.fs.totalBytes}`; CliUx.ux.log(progressString); - }); + }; - output.on('close', function () { + const onClose = () => { console.log(`Archive created successfully. Total bytes: ${archive.pointer()}`); + cleanup(); resolve(); - }); + }; - // Catch warnings (like stat failures and other non-blocking errors) - archive.on('warning', function (err) { + const onWarning = (err: Error & { code?: string }) => { if (err.code === 'ENOENT') { console.warn(err); } else { + cleanup(); reject(err); } - }); + }; - // Catch errors explicitly. - archive.on('error', function (err) { + const onError = (err: Error) => { CliUx.ux.error(err); + cleanup(); reject(err); - }); + }; + + const onOutputError = (err: Error) => { + cleanup(); + reject(err); + }; + + // Clean up all event listeners + const cleanup = () => { + archive.removeListener('progress', onProgress); + archive.removeListener('warning', onWarning); + archive.removeListener('error', onError); + output.removeListener('close', onClose); + output.removeListener('error', onOutputError); + }; + + // Add event listeners + archive.on('progress', onProgress); + archive.on('warning', onWarning); + archive.on('error', onError); + output.on('close', onClose); + output.on('error', onOutputError); + archive.pipe(output); // Append files from the source directory, preserving directory structure.