From 96d10c24857894ce76eca9d2e07e994919a3b14a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 07:48:58 +0000 Subject: [PATCH 1/2] build(deps): bump tar-stream from 3.2.0 to 3.2.1 Bumps [tar-stream](https://github.com/mafintosh/tar-stream) from 3.2.0 to 3.2.1. - [Commits](https://github.com/mafintosh/tar-stream/compare/v3.2.0...v3.2.1) --- updated-dependencies: - dependency-name: tar-stream dependency-version: 3.2.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 93d481a1..b200676f 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "js-yaml": "^5.4.1", "jwt-decode": "^4.0.0", "semver": "^7.8.5", - "tar-stream": "^3.2.0", + "tar-stream": "^3.2.1", "tmp": "^0.2.7" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index eb1baaaf..87c972c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -496,7 +496,7 @@ __metadata: prettier: "npm:^3.8.1" rimraf: "npm:^6.1.3" semver: "npm:^7.8.5" - tar-stream: "npm:^3.2.0" + tar-stream: "npm:^3.2.1" tmp: "npm:^0.2.7" typescript: "npm:^5.9.3" vitest: "npm:^4.0.18" @@ -4587,15 +4587,15 @@ __metadata: languageName: node linkType: hard -"tar-stream@npm:^3.2.0": - version: 3.2.0 - resolution: "tar-stream@npm:3.2.0" +"tar-stream@npm:^3.2.1": + version: 3.2.1 + resolution: "tar-stream@npm:3.2.1" dependencies: b4a: "npm:^1.6.4" bare-fs: "npm:^4.5.5" fast-fifo: "npm:^1.2.0" streamx: "npm:^2.15.0" - checksum: 10/ce57a81521de73ae7a3b7d55a08da50d6771427c249bfa89a208518e48faf5254c8fa7201a8f5419ab8bde9601a74e6dd512b31a13ec89774aec96178f99a8d3 + checksum: 10/1a09f857e0789489476d99fb716fa6d209e7d19aa73b7a4b23f40eeba46792d5007ca62fde4fca8f643ed71ace1c526a293c655718a0409275a45a8aa86b562a languageName: node linkType: hard From 4f9e7f24d4d0b5d46fa801a4d897f42a0a8c9679 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:00:53 +0200 Subject: [PATCH 2/2] oci: use tar-stream async extraction API Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- package.json | 1 - src/oci/oci.ts | 107 +++++++++++++++++++++++-------------------------- yarn.lock | 10 ----- 3 files changed, 51 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index b200676f..74baa3aa 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,6 @@ "@types/js-yaml": "^4.0.9", "@types/node": "^24.11.0", "@types/semver": "^7.7.1", - "@types/tar-stream": "^3.1.4", "@types/tmp": "^0.2.6", "@typescript-eslint/eslint-plugin": "^8.56.1", "@typescript-eslint/parser": "^8.56.1", diff --git a/src/oci/oci.ts b/src/oci/oci.ts index c1dff3a2..8e5386f7 100644 --- a/src/oci/oci.ts +++ b/src/oci/oci.ts @@ -75,66 +75,61 @@ export class OCI { }; } - public static loadArchive(opts: LoadArchiveOpts): Promise { - return new Promise((resolve, reject) => { - const tarex: tar.Extract = tar.extract(); - - let rootIndex: Index; - let rootLayout: ImageLayout; - const indexes: Record = {}; - const manifests: Record = {}; - const images: Record = {}; - const blobs: Record = {}; - - tarex.on('entry', async (header, stream, next) => { - if (header.type === 'file') { - const filename = path.normalize(header.name); - if (filename === IMAGE_INDEX_FILE_V1) { - rootIndex = await OCI.streamToJson(stream); - } else if (filename === IMAGE_LAYOUT_FILE_V1) { - rootLayout = await OCI.streamToJson(stream); - } else if (filename.startsWith(path.join(IMAGE_BLOBS_DIR_V1, path.sep))) { - const blob = await OCI.extractBlob(stream); - const digest = `${filename.split(path.sep)[1]}:${filename.split(path.sep)[filename.split(path.sep).length - 1]}`; - if (OCI.isIndex(blob)) { - indexes[digest] = JSON.parse(blob); - } else if (OCI.isManifest(blob)) { - manifests[digest] = JSON.parse(blob); - } else if (OCI.isImage(blob)) { - images[digest] = JSON.parse(blob); - } else { - blobs[digest] = blob; - } + public static async loadArchive(opts: LoadArchiveOpts): Promise { + const tarex = tar.extract(); + + let rootIndex: Index | undefined; + let rootLayout: ImageLayout | undefined; + const indexes: Record = {}; + const manifests: Record = {}; + const images: Record = {}; + const blobs: Record = {}; + + fs.createReadStream(opts.file) + .pipe(gunzip()) + .pipe(tarex as unknown as NodeJS.WritableStream); + + for await (const entry of tarex) { + const header = entry.header; + const stream = Readable.from(entry as unknown as AsyncIterable); + if (header.type === 'file') { + const filename = path.normalize(header.name); + if (filename === IMAGE_INDEX_FILE_V1) { + rootIndex = await OCI.streamToJson(stream); + } else if (filename === IMAGE_LAYOUT_FILE_V1) { + rootLayout = await OCI.streamToJson(stream); + } else if (filename.startsWith(path.join(IMAGE_BLOBS_DIR_V1, path.sep))) { + const blob = await OCI.extractBlob(stream); + const digest = `${filename.split(path.sep)[1]}:${filename.split(path.sep)[filename.split(path.sep).length - 1]}`; + if (OCI.isIndex(blob)) { + indexes[digest] = JSON.parse(blob); + } else if (OCI.isManifest(blob)) { + manifests[digest] = JSON.parse(blob); + } else if (OCI.isImage(blob)) { + images[digest] = JSON.parse(blob); } else { - reject(new Error(`Invalid OCI archive: unexpected file ${filename}`)); + blobs[digest] = blob; } + } else { + throw new Error(`Invalid OCI archive: unexpected file ${filename}`); } - stream.resume(); - next(); - }); - - tarex.on('finish', () => { - if (!rootIndex || !rootLayout) { - reject(new Error('Invalid OCI archive: missing index or layout')); - } - resolve({ - root: { - index: rootIndex, - layout: rootLayout - }, - indexes: indexes, - manifests: manifests, - images: images, - blobs: blobs - } as Archive); - }); - - tarex.on('error', error => { - reject(error); - }); + } + stream.resume(); + } + if (!rootIndex || !rootLayout) { + throw new Error('Invalid OCI archive: missing index or layout'); + } - fs.createReadStream(opts.file).pipe(gunzip()).pipe(tarex); - }); + return { + root: { + index: rootIndex, + layout: rootLayout + }, + indexes: indexes, + manifests: manifests, + images: images, + blobs: blobs + } as Archive; } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/yarn.lock b/yarn.lock index 87c972c7..5006a4a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -476,7 +476,6 @@ __metadata: "@types/js-yaml": "npm:^4.0.9" "@types/node": "npm:^24.11.0" "@types/semver": "npm:^7.7.1" - "@types/tar-stream": "npm:^3.1.4" "@types/tmp": "npm:^0.2.6" "@typescript-eslint/eslint-plugin": "npm:^8.56.1" "@typescript-eslint/parser": "npm:^8.56.1" @@ -1434,15 +1433,6 @@ __metadata: languageName: node linkType: hard -"@types/tar-stream@npm:^3.1.4": - version: 3.1.4 - resolution: "@types/tar-stream@npm:3.1.4" - dependencies: - "@types/node": "npm:*" - checksum: 10/9d1e182315c2189e18293b5a884edb9803c70772d37914870fbdb0bd659970e0d8effe002b19415ee251c422e3f169013668f3acf41feb9371040d0f0867d7b7 - languageName: node - linkType: hard - "@types/tmp@npm:^0.2.6": version: 0.2.6 resolution: "@types/tmp@npm:0.2.6"