2023-02-03 14:05:02 +01:00
|
|
|
import { Readable, Transform } from "stream";
|
2023-02-05 12:59:05 +01:00
|
|
|
import { dirname, relative, sep } from "path";
|
2023-02-03 14:05:02 +01:00
|
|
|
import { createWriteStream } from "fs";
|
|
|
|
|
|
|
|
import walk from "./walk";
|
2023-03-29 09:54:29 +02:00
|
|
|
import zip, { type ZipSource } from "./zip";
|
2023-02-05 12:59:05 +01:00
|
|
|
import { mkdir } from "fs/promises";
|
2023-03-29 09:54:29 +02:00
|
|
|
import trimIndent from "./trimIndent";
|
2023-02-03 14:05:02 +01:00
|
|
|
|
|
|
|
type JarArgs = {
|
|
|
|
rootPath: string;
|
|
|
|
targetPath: string;
|
|
|
|
groupId: string;
|
|
|
|
artifactId: string;
|
|
|
|
version: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
* the contents of the pom.properties file which is going to be added to the archive.
|
|
|
|
*/
|
|
|
|
export default async function jar({ groupId, artifactId, version, rootPath, targetPath }: JarArgs) {
|
|
|
|
const manifest: ZipSource = {
|
|
|
|
path: "META-INF/MANIFEST.MF",
|
2023-03-29 09:54:29 +02:00
|
|
|
data: Buffer.from(trimIndent`
|
|
|
|
Manifest-Version: 1.0
|
|
|
|
Archiver-Version: Plexus Archiver
|
|
|
|
Created-By: Keycloakify
|
|
|
|
Built-By: unknown
|
|
|
|
Build-Jdk: 19.0.0
|
|
|
|
`)
|
2023-02-03 14:05:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const pomProps: ZipSource = {
|
|
|
|
path: `META-INF/maven/${groupId}/${artifactId}/pom.properties`,
|
2023-03-29 09:54:29 +02:00
|
|
|
data: Buffer.from(trimIndent`# Generated by keycloakify
|
2023-03-29 18:07:43 -06:00
|
|
|
# ${new Date().toString()}
|
2023-03-29 09:54:29 +02:00
|
|
|
artifactId=${artifactId}
|
|
|
|
groupId=${groupId}
|
|
|
|
version=${version}
|
|
|
|
`)
|
2023-02-03 14:05:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert every path entry to a ZipSource record, and when all records are
|
|
|
|
* processed, append records for MANIFEST.mf and pom.properties
|
|
|
|
*/
|
|
|
|
const pathToRecord = () =>
|
|
|
|
new Transform({
|
|
|
|
objectMode: true,
|
2023-02-05 12:34:48 +01:00
|
|
|
transform: function (fsPath, _, cb) {
|
|
|
|
const path = relative(rootPath, fsPath).split(sep).join("/");
|
|
|
|
this.push({ path, fsPath });
|
2023-02-03 14:05:02 +01:00
|
|
|
cb();
|
|
|
|
},
|
|
|
|
final: function () {
|
|
|
|
this.push(manifest);
|
|
|
|
this.push(pomProps);
|
|
|
|
this.push(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-02-05 12:59:05 +01:00
|
|
|
await mkdir(dirname(targetPath), { recursive: true });
|
2023-02-05 13:32:24 +01:00
|
|
|
|
|
|
|
// Create an async pipeline, wait until everything is fully processed
|
|
|
|
await new Promise<void>((resolve, reject) => {
|
2023-02-03 14:05:02 +01:00
|
|
|
// walk all files in `rootPath` recursively
|
2023-02-05 13:32:24 +01:00
|
|
|
Readable.from(walk(rootPath))
|
|
|
|
// transform every path into a ZipSource object
|
|
|
|
.pipe(pathToRecord())
|
|
|
|
// let the zip lib convert all ZipSource objects into a byte stream
|
|
|
|
.pipe(zip())
|
|
|
|
// write that byte stream to targetPath
|
|
|
|
.pipe(createWriteStream(targetPath, { encoding: "binary" }))
|
|
|
|
.on("finish", () => resolve())
|
|
|
|
.on("error", e => reject(e));
|
|
|
|
});
|
2023-02-03 14:05:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Standalone usage, call e.g. `ts-node jar.ts dirWithSources some-jar.jar`
|
|
|
|
*/
|
|
|
|
if (require.main === module) {
|
|
|
|
const main = () =>
|
|
|
|
jar({
|
|
|
|
rootPath: process.argv[2],
|
|
|
|
targetPath: process.argv[3],
|
|
|
|
artifactId: process.env.ARTIFACT_ID ?? "artifact",
|
|
|
|
groupId: process.env.GROUP_ID ?? "group",
|
|
|
|
version: process.env.VERSION ?? "1.0.0"
|
|
|
|
});
|
2023-03-29 18:48:10 -06:00
|
|
|
main();
|
2023-02-03 14:05:02 +01:00
|
|
|
}
|