diff --git a/src/bin/tools/jar.ts b/src/bin/tools/jar.ts index 7ee4c694..d6fa26c9 100644 --- a/src/bin/tools/jar.ts +++ b/src/bin/tools/jar.ts @@ -6,63 +6,61 @@ import { ZipFile } from "yazl"; import { mkdir } from "fs/promises"; import trimIndent from "./trimIndent"; -export type ZipEntry = { zipPath: string } & ({ fsPath: string } | { buffer: Buffer }) -export type ZipEntryGenerator = AsyncGenerator +export type ZipEntry = { zipPath: string } & ({ fsPath: string } | { buffer: Buffer }); +export type ZipEntryGenerator = AsyncGenerator; type CommonJarArgs = { groupId: string; artifactId: string; version: string; -} +}; export type JarStreamArgs = CommonJarArgs & { - asyncPathGeneratorFn(): ZipEntryGenerator -} + asyncPathGeneratorFn(): ZipEntryGenerator; +}; export type JarArgs = CommonJarArgs & { targetPath: string; rootPath: string; }; - export async function jarStream({ groupId, artifactId, version, asyncPathGeneratorFn }: JarStreamArgs) { - const manifestPath = "META-INF/MANIFEST.MF" + const manifestPath = "META-INF/MANIFEST.MF"; const manifestData = Buffer.from(trimIndent` Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Keycloakify Built-By: unknown Build-Jdk: 19.0.0 - `) + `); - const pomPropsPath = `META-INF/maven/${groupId}/${artifactId}/pom.properties` + const pomPropsPath = `META-INF/maven/${groupId}/${artifactId}/pom.properties`; const pomPropsData = Buffer.from(trimIndent` # Generated by keycloakify # ${new Date()} artifactId=${artifactId} groupId=${groupId} version=${version} - `) + `); - const zipFile = new ZipFile() + const zipFile = new ZipFile(); for await (const entry of asyncPathGeneratorFn()) { if ("buffer" in entry) { - zipFile.addBuffer(entry.buffer, entry.zipPath) + zipFile.addBuffer(entry.buffer, entry.zipPath); } else if ("fsPath" in entry) { - zipFile.addFile(entry.fsPath, entry.zipPath) + zipFile.addFile(entry.fsPath, entry.zipPath); } } - zipFile.addBuffer(manifestData, manifestPath) - zipFile.addBuffer(pomPropsData, pomPropsPath) + zipFile.addBuffer(manifestData, manifestPath); + zipFile.addBuffer(pomPropsData, pomPropsPath); - zipFile.end() + zipFile.end(); - return zipFile + return zipFile; } - /** * Create a jar archive, using the resources found at `rootPath` (a directory) and write the * archive to `targetPath` (a file). Use `groupId`, `artifactId` and `version` to define @@ -71,18 +69,19 @@ export async function jarStream({ groupId, artifactId, version, asyncPathGenerat export default async function jar({ groupId, artifactId, version, rootPath, targetPath }: JarArgs) { await mkdir(dirname(targetPath), { recursive: true }); - const asyncPathGeneratorFn = (async function* (): ZipEntryGenerator { + const asyncPathGeneratorFn = async function* (): ZipEntryGenerator { for await (const fsPath of walk(rootPath)) { const zipPath = relative(rootPath, fsPath).split(sep).join("/"); - yield ({ fsPath, zipPath }) + yield { fsPath, zipPath }; } - }) + }; - const zipFile = await jarStream({ groupId, artifactId, version, asyncPathGeneratorFn }) + const zipFile = await jarStream({ groupId, artifactId, version, asyncPathGeneratorFn }); await new Promise(async (resolve, reject) => { - zipFile.outputStream.pipe(createWriteStream(targetPath, { encoding: "binary" })) + zipFile.outputStream + .pipe(createWriteStream(targetPath, { encoding: "binary" })) .on("close", () => resolve()) - .on("error", e => reject(e)) + .on("error", e => reject(e)); }); } diff --git a/test/bin/jar.spec.ts b/test/bin/jar.spec.ts index e2390734..7f50637c 100644 --- a/test/bin/jar.spec.ts +++ b/test/bin/jar.spec.ts @@ -5,74 +5,82 @@ import { Readable } from "stream"; type AsyncIterable = { [Symbol.asyncIterator](): AsyncIterableIterator; -} +}; async function arrayFromAsync(asyncIterable: AsyncIterable) { - const chunks: T[] = [] - for await (const chunk of asyncIterable) chunks.push(chunk) - return chunks + const chunks: T[] = []; + for await (const chunk of asyncIterable) chunks.push(chunk); + return chunks; } async function readToBuffer(stream: NodeJS.ReadableStream) { - return Buffer.concat(await arrayFromAsync(stream as AsyncIterable)) + return Buffer.concat(await arrayFromAsync(stream as AsyncIterable)); } function unzip(buffer: Buffer) { return new Promise((resolve, reject) => fromBuffer(buffer, { lazyEntries: true }, (err, zipFile) => { - if (err !== null) { reject(err) } else { resolve(zipFile) } - })) + if (err !== null) { + reject(err); + } else { + resolve(zipFile); + } + }) + ); } function readEntry(zipFile: ZipFile, entry: Entry): Promise { return new Promise((resolve, reject) => { zipFile.openReadStream(entry, (err, stream) => { - if (err !== null) { reject(err) } else { resolve(stream) } - }) - }) + if (err !== null) { + reject(err); + } else { + resolve(stream); + } + }); + }); } function readAll(zipFile: ZipFile): Promise> { return new Promise>((resolve, reject) => { - const entries1: Map = new Map() + const entries1: Map = new Map(); zipFile.on("entry", async (entry: Entry) => { - const stream = await readEntry(zipFile, entry) - const buffer = await readToBuffer(stream) - entries1.set(entry.fileName, buffer) - zipFile.readEntry() - }) - zipFile.on("end", () => resolve(entries1)) - zipFile.on("error", e => reject(e)) - zipFile.readEntry() - }) + const stream = await readEntry(zipFile, entry); + const buffer = await readToBuffer(stream); + entries1.set(entry.fileName, buffer); + zipFile.readEntry(); + }); + zipFile.on("end", () => resolve(entries1)); + zipFile.on("error", e => reject(e)); + zipFile.readEntry(); + }); } describe("jar", () => { it("creates jar artifacts without error", async () => { async function* mockFiles(): ZipEntryGenerator { - yield { zipPath: "foo", buffer: Buffer.from("foo") } + yield { zipPath: "foo", buffer: Buffer.from("foo") }; } - const opts = { artifactId: "someArtifactId", groupId: "someGroupId", version: "1.2.3", asyncPathGeneratorFn: mockFiles } + const opts = { artifactId: "someArtifactId", groupId: "someGroupId", version: "1.2.3", asyncPathGeneratorFn: mockFiles }; const zipped = await jarStream(opts); - const buffered = await readToBuffer(zipped.outputStream) - const unzipped = await unzip(buffered) - const entries = await readAll(unzipped) + const buffered = await readToBuffer(zipped.outputStream); + const unzipped = await unzip(buffered); + const entries = await readAll(unzipped); - assert.equal(entries.size, 3) - assert.isOk(entries.has("foo")) - assert.isOk(entries.has("META-INF/MANIFEST.MF")) - assert.isOk(entries.has("META-INF/maven/someGroupId/someArtifactId/pom.properties")) + assert.equal(entries.size, 3); + assert.isOk(entries.has("foo")); + assert.isOk(entries.has("META-INF/MANIFEST.MF")); + assert.isOk(entries.has("META-INF/maven/someGroupId/someArtifactId/pom.properties")); - assert.equal("foo", entries.get("foo")?.toString("utf-8")) + assert.equal("foo", entries.get("foo")?.toString("utf-8")); - const manifest = entries.get("META-INF/MANIFEST.MF")?.toString("utf-8") - const pomProperties = entries.get("META-INF/maven/someGroupId/someArtifactId/pom.properties")?.toString("utf-8") - - assert.isOk(manifest?.includes("Created-By: Keycloakify")) - assert.isOk(pomProperties?.includes("1.2.3")) - assert.isOk(pomProperties?.includes("someGroupId")) - assert.isOk(pomProperties?.includes("someArtifactId")) + const manifest = entries.get("META-INF/MANIFEST.MF")?.toString("utf-8"); + const pomProperties = entries.get("META-INF/maven/someGroupId/someArtifactId/pom.properties")?.toString("utf-8"); + assert.isOk(manifest?.includes("Created-By: Keycloakify")); + assert.isOk(pomProperties?.includes("1.2.3")); + assert.isOk(pomProperties?.includes("someGroupId")); + assert.isOk(pomProperties?.includes("someArtifactId")); }); });