diff --git a/src/bin/start-keycloak/appBuild.ts b/src/bin/start-keycloak/appBuild.ts index 0fd32553..24d9041c 100644 --- a/src/bin/start-keycloak/appBuild.ts +++ b/src/bin/start-keycloak/appBuild.ts @@ -1,18 +1,17 @@ import * as child_process from "child_process"; 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 chalk from "chalk"; import { sep as pathSep, join as pathJoin } from "path"; import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath"; import * as fs from "fs"; import { dirname as pathDirname, relative as pathRelative } from "path"; +import { z } from "zod"; export type BuildContextLike = { projectDirPath: string; - keycloakifyBuildDirPath: string; - bundler: BuildContext["bundler"]; - projectBuildDirPath: string; packageJsonFilePath: string; }; @@ -23,58 +22,36 @@ export async function appBuild(params: { }): Promise<{ isAppBuildSuccess: boolean }> { const { buildContext } = params; - switch (buildContext.bundler) { - case "vite": - return appBuild_vite({ buildContext }); - case "webpack": - return appBuild_webpack({ buildContext }); - } -} + const { parsedPackageJson } = (() => { + type ParsedPackageJson = { + scripts?: Record; + }; -async function appBuild_vite(params: { - buildContext: BuildContextLike; -}): Promise<{ isAppBuildSuccess: boolean }> { - const { buildContext } = params; + const zParsedPackageJson = (() => { + type TargetType = ParsedPackageJson; - assert(buildContext.bundler === "vite"); + const zTargetType = z.object({ + scripts: z.record(z.string()).optional() + }); - const dIsSuccess = new Deferred(); + assert, TargetType>>(); - console.log(chalk.blue("$ npx vite build")); + return id>(zTargetType); + })(); + const parsedPackageJson = JSON.parse( + fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8") + ); - const child = child_process.spawn("npx", ["vite", "build"], { - cwd: buildContext.projectDirPath, - shell: true - }); + zParsedPackageJson.parse(parsedPackageJson); - child.stdout.on("data", data => { - if (data.toString("utf8").includes("gzip:")) { - return; - } + assert(is(parsedPackageJson)); - process.stdout.write(data); - }); + return { parsedPackageJson }; + })(); - 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 }; -} - -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 - ).filter(([, scriptCommand]) => scriptCommand.includes("keycloakify build")); + const entries = Object.entries(parsedPackageJson.scripts ?? {}).filter( + ([, scriptCommand]) => scriptCommand.includes("keycloakify build") + ); if (entries.length === 0) { console.log( @@ -127,6 +104,76 @@ async function appBuild_webpack(params: { 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(); + + 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); for (const subCommand of appBuildSubCommands) {