Smarter appBuild script

This commit is contained in:
Joseph Garrone 2024-12-08 19:42:43 +01:00
parent f4829b557f
commit b0ba37fcc4

View File

@ -1,18 +1,17 @@
import * as child_process from "child_process"; import * as child_process from "child_process";
import { Deferred } from "evt/tools/Deferred"; import { Deferred } from "evt/tools/Deferred";
import { assert } from "tsafe/assert"; import { assert, is, type Equals } from "tsafe/assert";
import { id } from "tsafe/id";
import type { BuildContext } from "../shared/buildContext"; import type { BuildContext } from "../shared/buildContext";
import chalk from "chalk"; import chalk from "chalk";
import { sep as pathSep, join as pathJoin } from "path"; import { sep as pathSep, join as pathJoin } from "path";
import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath"; import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
import * as fs from "fs"; import * as fs from "fs";
import { dirname as pathDirname, relative as pathRelative } from "path"; import { dirname as pathDirname, relative as pathRelative } from "path";
import { z } from "zod";
export type BuildContextLike = { export type BuildContextLike = {
projectDirPath: string; projectDirPath: string;
keycloakifyBuildDirPath: string;
bundler: BuildContext["bundler"];
projectBuildDirPath: string;
packageJsonFilePath: string; packageJsonFilePath: string;
}; };
@ -23,58 +22,36 @@ export async function appBuild(params: {
}): Promise<{ isAppBuildSuccess: boolean }> { }): Promise<{ isAppBuildSuccess: boolean }> {
const { buildContext } = params; const { buildContext } = params;
switch (buildContext.bundler) { const { parsedPackageJson } = (() => {
case "vite": type ParsedPackageJson = {
return appBuild_vite({ buildContext }); scripts?: Record<string, string>;
case "webpack": };
return appBuild_webpack({ buildContext });
}
}
async function appBuild_vite(params: { const zParsedPackageJson = (() => {
buildContext: BuildContextLike; type TargetType = ParsedPackageJson;
}): Promise<{ isAppBuildSuccess: boolean }> {
const { buildContext } = params;
assert(buildContext.bundler === "vite"); const zTargetType = z.object({
scripts: z.record(z.string()).optional()
});
const dIsSuccess = new Deferred<boolean>(); assert<Equals<z.infer<typeof zTargetType>, TargetType>>();
console.log(chalk.blue("$ npx vite build")); return id<z.ZodType<TargetType>>(zTargetType);
})();
const parsedPackageJson = JSON.parse(
fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8")
);
const child = child_process.spawn("npx", ["vite", "build"], { zParsedPackageJson.parse(parsedPackageJson);
cwd: buildContext.projectDirPath,
shell: true
});
child.stdout.on("data", data => { assert(is<ParsedPackageJson>(parsedPackageJson));
if (data.toString("utf8").includes("gzip:")) {
return;
}
process.stdout.write(data); return { parsedPackageJson };
}); })();
child.stderr.on("data", data => process.stderr.write(data)); const entries = Object.entries(parsedPackageJson.scripts ?? {}).filter(
([, scriptCommand]) => scriptCommand.includes("keycloakify build")
child.on("exit", code => dIsSuccess.resolve(code === 0)); );
const isSuccess = await dIsSuccess.pr;
return { isAppBuildSuccess: isSuccess };
}
async function appBuild_webpack(params: {
buildContext: BuildContextLike;
}): Promise<{ isAppBuildSuccess: boolean }> {
const { buildContext } = params;
assert(buildContext.bundler === "webpack");
const entries = Object.entries(
(JSON.parse(fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8"))
.scripts ?? {}) as Record<string, string>
).filter(([, scriptCommand]) => scriptCommand.includes("keycloakify build"));
if (entries.length === 0) { if (entries.length === 0) {
console.log( console.log(
@ -127,6 +104,76 @@ async function appBuild_webpack(params: {
process.exit(-1); process.exit(-1);
} }
common_case: {
if (appBuildSubCommands.length !== 1) {
break common_case;
}
const [appBuildSubCommand] = appBuildSubCommands;
const isNpmRunBuild = (() => {
for (const packageManager of ["npm", "yarn", "pnpm", "bun", "deno"]) {
for (const doUseRun of [true, false]) {
if (
`${packageManager}${doUseRun ? " run " : " "}build` ===
appBuildSubCommand
) {
return true;
}
}
}
return false;
})();
if (!isNpmRunBuild) {
break common_case;
}
const { scripts } = parsedPackageJson;
assert(scripts !== undefined);
const buildCmd = scripts.build;
if (buildCmd !== "tsc && vite build") {
break common_case;
}
if (scripts.prebuild !== undefined) {
break common_case;
}
if (scripts.postbuild !== undefined) {
break common_case;
}
const dIsSuccess = new Deferred<boolean>();
console.log(chalk.blue("$ npx vite build"));
const child = child_process.spawn("npx", ["vite", "build"], {
cwd: buildContext.projectDirPath,
shell: true
});
child.stdout.on("data", data => {
if (data.toString("utf8").includes("gzip:")) {
return;
}
process.stdout.write(data);
});
child.stderr.on("data", data => process.stderr.write(data));
child.on("exit", code => dIsSuccess.resolve(code === 0));
const isSuccess = await dIsSuccess.pr;
return { isAppBuildSuccess: isSuccess };
}
let commandCwd = pathDirname(buildContext.packageJsonFilePath); let commandCwd = pathDirname(buildContext.packageJsonFilePath);
for (const subCommand of appBuildSubCommands) { for (const subCommand of appBuildSubCommands) {