From ad70a4cffdc6abb4474e9ab2947fe0c91081037a Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 11 Feb 2024 20:15:18 +0100 Subject: [PATCH] Make Vite run copy-keaycloak-resources-to-public --- src/bin/copy-keycloak-resources-to-public.ts | 82 +++++++++++++++++-- src/bin/eject-keycloak-page.ts | 4 +- src/bin/keycloakify/keycloakify.ts | 18 ++-- ...tRoot.ts => getThisCodebaseRootDirPath.ts} | 8 +- src/bin/tools/grant-exec-perms.ts | 8 +- src/bin/tools/readThisNpmProjectVersion.ts | 12 +++ src/vite-plugin/vite-plugin.ts | 7 +- 7 files changed, 108 insertions(+), 31 deletions(-) rename src/bin/tools/{getProjectRoot.ts => getThisCodebaseRootDirPath.ts} (50%) create mode 100644 src/bin/tools/readThisNpmProjectVersion.ts diff --git a/src/bin/copy-keycloak-resources-to-public.ts b/src/bin/copy-keycloak-resources-to-public.ts index 987a0d64..c74e571c 100644 --- a/src/bin/copy-keycloak-resources-to-public.ts +++ b/src/bin/copy-keycloak-resources-to-public.ts @@ -1,17 +1,43 @@ #!/usr/bin/env node -import { downloadKeycloakStaticResources } from "./keycloakify/generateTheme/downloadKeycloakStaticResources"; +import { downloadKeycloakStaticResources, type BuildOptionsLike } from "./keycloakify/generateTheme/downloadKeycloakStaticResources"; import { join as pathJoin } from "path"; import { readBuildOptions } from "./keycloakify/buildOptions"; import { themeTypes, keycloak_resources, lastKeycloakVersionWithAccountV1 } from "./constants"; +import { readThisNpmProjectVersion } from "./tools/readThisNpmProjectVersion"; +import { assert, type Equals } from "tsafe/assert"; import * as fs from "fs"; +import { rmSync } from "./tools/fs.rmSync"; -(async () => { - const buildOptions = readBuildOptions({ - "processArgv": process.argv.slice(2) +export async function copyKeycloakResourcesToPublic(params: { processArgv: string[] }) { + const { processArgv } = params; + + const buildOptions = readBuildOptions({ processArgv }); + + const destDirPath = pathJoin(buildOptions.publicDirPath, keycloak_resources); + + const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo"); + + const { keycloakifyBuildinfoRaw } = generateKeycloakifyBuildinfoRaw({ + "keycloakifyVersion": readThisNpmProjectVersion(), + buildOptions }); - const reservedDirPath = pathJoin(buildOptions.publicDirPath, keycloak_resources); + skip_if_already_done: { + if (!fs.existsSync(keycloakifyBuildinfoFilePath)) { + break skip_if_already_done; + } + + const keycloakifyBuildinfoRaw_previousRun = fs.readFileSync(keycloakifyBuildinfoFilePath).toString("utf8"); + + if (keycloakifyBuildinfoRaw_previousRun !== keycloakifyBuildinfoRaw) { + break skip_if_already_done; + } + + return; + } + + rmSync(destDirPath, { "force": true, "recursive": true }); for (const themeType of themeTypes) { await downloadKeycloakStaticResources({ @@ -24,13 +50,13 @@ import * as fs from "fs"; } })(), themeType, - "themeDirPath": reservedDirPath, + "themeDirPath": destDirPath, buildOptions }); } fs.writeFileSync( - pathJoin(reservedDirPath, "README.txt"), + pathJoin(destDirPath, "README.txt"), Buffer.from( // prettier-ignore [ @@ -41,4 +67,44 @@ import * as fs from "fs"; ); fs.writeFileSync(pathJoin(buildOptions.publicDirPath, keycloak_resources, ".gitignore"), Buffer.from("*", "utf8")); -})(); + + fs.writeFileSync(keycloakifyBuildinfoFilePath, Buffer.from(keycloakifyBuildinfoRaw, "utf8")); +} + +export function generateKeycloakifyBuildinfoRaw(params: { + keycloakifyVersion: string; + buildOptions: BuildOptionsLike & { + loginThemeResourcesFromKeycloakVersion: string; + }; +}) { + const { keycloakifyVersion, buildOptions } = params; + + const { cacheDirPath, npmWorkspaceRootDirPath, loginThemeResourcesFromKeycloakVersion, ...rest } = buildOptions; + + assert>(true); + + const keycloakifyBuildinfoRaw = JSON.stringify( + { + keycloakifyVersion, + "buildOptions": { + loginThemeResourcesFromKeycloakVersion, + cacheDirPath, + npmWorkspaceRootDirPath + } + }, + null, + 2 + ); + + return { keycloakifyBuildinfoRaw }; +} + +async function main() { + await copyKeycloakResourcesToPublic({ + "processArgv": process.argv.slice(2) + }); +} + +if (require.main === module) { + main(); +} diff --git a/src/bin/eject-keycloak-page.ts b/src/bin/eject-keycloak-page.ts index 19332bd1..f777f281 100644 --- a/src/bin/eject-keycloak-page.ts +++ b/src/bin/eject-keycloak-page.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node -import { getProjectRoot } from "./tools/getProjectRoot"; +import { getThisCodebaseRootDirPath } from "./tools/getThisCodebaseRootDirPath"; import cliSelect from "cli-select"; import { loginThemePageIds, accountThemePageIds, type LoginThemePageId, type AccountThemePageId } from "./keycloakify/generateFtl"; import { capitalize } from "tsafe/capitalize"; @@ -58,7 +58,7 @@ import { getReactAppRootDirPath } from "./keycloakify/buildOptions/getReactAppRo process.exit(-1); } - await writeFile(targetFilePath, await readFile(pathJoin(getProjectRoot(), "src", themeType, "pages", pageBasename))); + await writeFile(targetFilePath, await readFile(pathJoin(getThisCodebaseRootDirPath(), "src", themeType, "pages", pageBasename))); console.log(`${pathRelative(process.cwd(), targetFilePath)} created`); })(); diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index f5209b16..9a03bd5a 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -6,9 +6,9 @@ import { generateStartKeycloakTestingContainer } from "./generateStartKeycloakTe import * as fs from "fs"; import { readBuildOptions } from "./buildOptions"; import { getLogger } from "../tools/logger"; -import { assert } from "tsafe/assert"; import { getThemeSrcDirPath } from "../getThemeSrcDirPath"; -import { getProjectRoot } from "../tools/getProjectRoot"; +import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath"; +import { readThisNpmProjectVersion } from "../tools/readThisNpmProjectVersion"; export async function main() { const buildOptions = readBuildOptions({ @@ -18,23 +18,15 @@ export async function main() { const logger = getLogger({ "isSilent": buildOptions.isSilent }); logger.log("🔏 Building the keycloak theme...⌚"); - const keycloakifyDirPath = getProjectRoot(); - const { themeSrcDirPath } = getThemeSrcDirPath({ "reactAppRootDirPath": buildOptions.reactAppRootDirPath }); for (const themeName of buildOptions.themeNames) { await generateTheme({ themeName, themeSrcDirPath, - "keycloakifySrcDirPath": pathJoin(keycloakifyDirPath, "src"), - buildOptions, - "keycloakifyVersion": (() => { - const version = JSON.parse(fs.readFileSync(pathJoin(keycloakifyDirPath, "package.json")).toString("utf8"))["version"]; - - assert(typeof version === "string"); - - return version; - })() + "keycloakifySrcDirPath": pathJoin(getThisCodebaseRootDirPath(), "src"), + "keycloakifyVersion": readThisNpmProjectVersion(), + buildOptions }); } diff --git a/src/bin/tools/getProjectRoot.ts b/src/bin/tools/getThisCodebaseRootDirPath.ts similarity index 50% rename from src/bin/tools/getProjectRoot.ts rename to src/bin/tools/getThisCodebaseRootDirPath.ts index 4d4ea107..f880ffc9 100644 --- a/src/bin/tools/getProjectRoot.ts +++ b/src/bin/tools/getThisCodebaseRootDirPath.ts @@ -1,19 +1,19 @@ import * as fs from "fs"; import * as path from "path"; -function getProjectRootRec(dirPath: string): string { +function getThisCodebaseRootDirPath_rec(dirPath: string): string { if (fs.existsSync(path.join(dirPath, "package.json"))) { return dirPath; } - return getProjectRootRec(path.join(dirPath, "..")); + return getThisCodebaseRootDirPath_rec(path.join(dirPath, "..")); } let result: string | undefined = undefined; -export function getProjectRoot(): string { +export function getThisCodebaseRootDirPath(): string { if (result !== undefined) { return result; } - return (result = getProjectRootRec(__dirname)); + return (result = getThisCodebaseRootDirPath_rec(__dirname)); } diff --git a/src/bin/tools/grant-exec-perms.ts b/src/bin/tools/grant-exec-perms.ts index 315f39bb..50abb0be 100644 --- a/src/bin/tools/grant-exec-perms.ts +++ b/src/bin/tools/grant-exec-perms.ts @@ -1,13 +1,15 @@ -import { getProjectRoot } from "./getProjectRoot"; +import { getThisCodebaseRootDirPath } from "./getThisCodebaseRootDirPath"; import { join as pathJoin } from "path"; import { constants } from "fs"; import { chmod, stat } from "fs/promises"; (async () => { - const { bin } = await import(pathJoin(getProjectRoot(), "package.json")); + const thisCodebaseRootDirPath = getThisCodebaseRootDirPath(); + + const { bin } = await import(pathJoin(thisCodebaseRootDirPath, "package.json")); const promises = Object.values(bin).map(async scriptPath => { - const fullPath = pathJoin(getProjectRoot(), scriptPath); + const fullPath = pathJoin(thisCodebaseRootDirPath, scriptPath); const oldMode = (await stat(fullPath)).mode; const newMode = oldMode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH; await chmod(fullPath, newMode); diff --git a/src/bin/tools/readThisNpmProjectVersion.ts b/src/bin/tools/readThisNpmProjectVersion.ts new file mode 100644 index 00000000..e99f97e8 --- /dev/null +++ b/src/bin/tools/readThisNpmProjectVersion.ts @@ -0,0 +1,12 @@ +import { getThisCodebaseRootDirPath } from "./getThisCodebaseRootDirPath"; +import { assert } from "tsafe/assert"; +import * as fs from "fs"; +import { join as pathJoin } from "path"; + +export function readThisNpmProjectVersion(): string { + const version = JSON.parse(fs.readFileSync(pathJoin(getThisCodebaseRootDirPath(), "package.json")).toString("utf8"))["version"]; + + assert(typeof version === "string"); + + return version; +} diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts index b2655202..ca0e931f 100644 --- a/src/vite-plugin/vite-plugin.ts +++ b/src/vite-plugin/vite-plugin.ts @@ -8,6 +8,7 @@ import { getCacheDirPath } from "../bin/keycloakify/buildOptions/getCacheDirPath import { replaceAll } from "../bin/tools/String.prototype.replaceAll"; import { id } from "tsafe/id"; import { rm } from "../bin/tools/fs.rm"; +import { copyKeycloakResourcesToPublic } from "../bin/copy-keycloak-resources-to-public"; export function keycloakify(): Plugin { let reactAppRootDirPath: string | undefined = undefined; @@ -17,7 +18,7 @@ export function keycloakify(): Plugin { return { "name": "keycloakify", "apply": "build", - "configResolved": resolvedConfig => { + "configResolved": async resolvedConfig => { reactAppRootDirPath = resolvedConfig.root; urlPathname = (() => { let out = resolvedConfig.env.BASE_URL; @@ -63,6 +64,10 @@ export function keycloakify(): Plugin { "utf8" ) ); + + await copyKeycloakResourcesToPublic({ + "processArgv": ["--project", reactAppRootDirPath] + }); }, "transform": (code, id) => { assert(reactAppRootDirPath !== undefined);