diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index 9cbe792f..e05e237f 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -11,15 +11,15 @@ import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion"; import * as os from "os"; export async function command(params: { cliCommandOptions: CliCommandOptions }) { - check_if_maven_is_installed: { + exit_if_maven_not_installed: { let commandOutput: Buffer | undefined = undefined; try { - commandOutput = child_process.execSync("mvn --version"); + commandOutput = child_process.execSync("mvn --version", { "stdio": ["ignore", "pipe", "ignore"] }); } catch {} if (!commandOutput?.toString("utf8").includes("Apache Maven")) { - break check_if_maven_is_installed; + break exit_if_maven_not_installed; } const installationCommand = (() => { diff --git a/src/bin/main.ts b/src/bin/main.ts index 2fead8d8..f3e0f845 100644 --- a/src/bin/main.ts +++ b/src/bin/main.ts @@ -65,10 +65,34 @@ program }); program - .command({ + .command<{ port: number; keycloakVersion: string | undefined }>({ "name": "start-keycloak", "description": "Spin up a pre configured Docker image of Keycloak to test your theme." }) + .option({ + "key": "port", + "name": (() => { + const name = "port"; + + optionsKeys.push(name); + + return name; + })(), + "description": "Keycloak server port.", + "defaultValue": 8080 + }) + .option({ + "key": "keycloakVersion", + "name": (() => { + const name = "keycloak-version"; + + optionsKeys.push(name); + + return name; + })(), + "description": "Use a specific version of Keycloak.", + "defaultValue": undefined + }) .task({ skip, "handler": cliCommandOptions => diff --git a/src/bin/start-keycloak.ts b/src/bin/start-keycloak.ts index 9fcd98e5..5dd83a3d 100644 --- a/src/bin/start-keycloak.ts +++ b/src/bin/start-keycloak.ts @@ -1,5 +1,5 @@ import { readBuildOptions } from "./shared/buildOptions"; -import type { CliCommandOptions } from "./main"; +import type { CliCommandOptions as CliCommandOptions_common } from "./main"; import { promptKeycloakVersion } from "./shared/promptKeycloakVersion"; import { readMetaInfKeycloakThemes } from "./shared/metaInfKeycloakThemes"; import { accountV1ThemeName } from "./shared/constants"; @@ -12,16 +12,21 @@ import { join as pathJoin, posix as pathPosix } from "path"; import * as child_process from "child_process"; import chalk from "chalk"; +export type CliCommandOptions = CliCommandOptions_common & { + port: number; + keycloakVersion: string | undefined; +}; + export async function command(params: { cliCommandOptions: CliCommandOptions }) { - check_if_docker_installed: { + exit_if_docker_not_installed: { let commandOutput: Buffer | undefined = undefined; try { - commandOutput = child_process.execSync("docker --version"); + commandOutput = child_process.execSync("docker --version", { "stdio": ["ignore", "pipe", "ignore"] }); } catch {} - if (!commandOutput?.toString("utf8").includes("Docker")) { - break check_if_docker_installed; + if (commandOutput?.toString("utf8").includes("Docker")) { + break exit_if_docker_not_installed; } console.log( @@ -35,39 +40,59 @@ export async function command(params: { cliCommandOptions: CliCommandOptions }) process.exit(1); } - check_if_docker_is_running: { + exit_if_docker_not_running: { let isDockerRunning: boolean; try { - child_process.execSync("docker info"); + child_process.execSync("docker info", { "stdio": "ignore" }); isDockerRunning = true; } catch { isDockerRunning = false; } if (isDockerRunning) { - break check_if_docker_is_running; + break exit_if_docker_not_running; } console.log([`${chalk.red("Docker daemon is not running.")}`, `Please start Docker Desktop and try again.`].join(" ")); + + process.exit(1); } const { cliCommandOptions } = params; const buildOptions = readBuildOptions({ cliCommandOptions }); + exit_if_theme_not_built: { + if (fs.existsSync(buildOptions.keycloakifyBuildDirPath)) { + break exit_if_theme_not_built; + } + + console.log( + [`${chalk.red("The theme has not been built.")}`, `Please run ${chalk.bold("npx vite && npx keycloakify build")} first.`].join(" ") + ); + process.exit(1); + } + const metaInfKeycloakThemes = readMetaInfKeycloakThemes({ "keycloakifyBuildDirPath": buildOptions.keycloakifyBuildDirPath }); const doesImplementAccountTheme = metaInfKeycloakThemes.themes.some(({ name }) => name === accountV1ThemeName); - console.log("On which version of Keycloak do you want to test your theme?"); - const { keycloakVersion, keycloakMajorNumber } = await (async function getKeycloakMajor(): Promise<{ keycloakVersion: string; keycloakMajorNumber: number; }> { + if (cliCommandOptions.keycloakVersion !== undefined) { + return { + "keycloakVersion": cliCommandOptions.keycloakVersion, + "keycloakMajorNumber": SemVer.parse(cliCommandOptions.keycloakVersion).major + }; + } + + console.log("On which version of Keycloak do you want to test your theme?"); + const { keycloakVersion } = await promptKeycloakVersion({ "startingFromMajor": 17, "cacheDirPath": buildOptions.cacheDirPath @@ -160,13 +185,11 @@ export async function command(params: { cliCommandOptions: CliCommandOptions }) child_process.execSync(`docker rm ${containerName}`, { "stdio": "ignore" }); } catch {} - const externalPort = 8080; - const child = child_process.spawn( "docker", [ "run", - ...["-p", `${externalPort}:8080`], + ...["-p", `${cliCommandOptions.port}:8080`], ...["--name", containerName], ...["-e", "KEYCLOAK_ADMIN=admin"], ...["-e", "KEYCLOAK_ADMIN_PASSWORD=admin"], @@ -198,7 +221,6 @@ export async function command(params: { cliCommandOptions: CliCommandOptions }) console.log( [ - "", "", `${chalk.green("Your theme is accessible at:")}`, `${chalk.green("➜")} ${chalk.cyan.bold("https://test.keycloakify.dev/")}`,