import { relative as pathRelative } from "path"; import { downloadAndExtractArchive } from "../../src/bin/tools/downloadAndExtractArchive"; import { getProxyFetchOptions } from "../../src/bin/tools/fetchProxyOptions"; import { join as pathJoin } from "path"; import { getThisCodebaseRootDirPath } from "../../src/bin/tools/getThisCodebaseRootDirPath"; import { assert, type Equals } from "tsafe/assert"; const KEYCLOAK_VERSION = { FOR_LOGIN_THEME: "25.0.4", FOR_ACCOUNT_MULTI_PAGE: "21.1.2" } as const; export async function downloadKeycloakDefaultTheme(params: { keycloakVersionId: keyof typeof KEYCLOAK_VERSION; }) { const { keycloakVersionId } = params; const keycloakVersion = KEYCLOAK_VERSION[keycloakVersionId]; let kcNodeModulesKeepFilePaths: Set | undefined = undefined; let kcNodeModulesKeepFilePaths_lastAccountV1: Set | undefined = undefined; const { extractedDirPath } = await downloadAndExtractArchive({ url: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`, cacheDirPath: pathJoin( getThisCodebaseRootDirPath(), "node_modules", ".cache", "scripts" ), fetchOptions: getProxyFetchOptions({ npmConfigGetCwd: getThisCodebaseRootDirPath() }), uniqueIdOfOnArchiveFile: "extractOnlyRequiredFiles", onArchiveFile: async params => { const fileRelativePath = pathRelative("theme", params.fileRelativePath); if (fileRelativePath.startsWith("..")) { return; } const { readFile, writeFile } = params; if ( !fileRelativePath.startsWith("base") && !fileRelativePath.startsWith("keycloak") ) { return; } switch (keycloakVersion) { case KEYCLOAK_VERSION.FOR_LOGIN_THEME: if ( !fileRelativePath.startsWith(pathJoin("base", "login")) && !fileRelativePath.startsWith(pathJoin("keycloak", "login")) && !fileRelativePath.startsWith(pathJoin("keycloak", "common")) ) { return; } if (fileRelativePath.endsWith(".ftl")) { return; } break; case KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE: if ( !fileRelativePath.startsWith(pathJoin("base", "account")) && !fileRelativePath.startsWith(pathJoin("keycloak", "account")) && !fileRelativePath.startsWith(pathJoin("keycloak", "common")) ) { return; } break; default: assert>(false); } last_account_v1_transformations: { if (keycloakVersion !== KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE) { break last_account_v1_transformations; } skip_web_modules: { if ( !fileRelativePath.startsWith( pathJoin("keycloak", "common", "resources", "web_modules") ) ) { break skip_web_modules; } return; } skip_lib: { if ( !fileRelativePath.startsWith( pathJoin("keycloak", "common", "resources", "lib") ) ) { break skip_lib; } return; } skip_node_modules: { const nodeModulesRelativeDirPath = pathJoin( "keycloak", "common", "resources", "node_modules" ); if (!fileRelativePath.startsWith(nodeModulesRelativeDirPath)) { break skip_node_modules; } if (kcNodeModulesKeepFilePaths_lastAccountV1 === undefined) { kcNodeModulesKeepFilePaths_lastAccountV1 = new Set([ pathJoin("patternfly", "dist", "css", "patternfly.min.css"), pathJoin( "patternfly", "dist", "css", "patternfly-additions.min.css" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Regular-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Bold-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Light-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Semibold-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "PatternFlyIcons-webfont.ttf" ), pathJoin( "patternfly", "dist", "fonts", "PatternFlyIcons-webfont.woff" ) ]); } const fileRelativeToNodeModulesPath = fileRelativePath.substring( nodeModulesRelativeDirPath.length + 1 ); if ( kcNodeModulesKeepFilePaths_lastAccountV1.has( fileRelativeToNodeModulesPath ) ) { break skip_node_modules; } return; } patch_account_css: { if ( fileRelativePath !== pathJoin("keycloak", "account", "resources", "css", "account.css") ) { break patch_account_css; } await writeFile({ fileRelativePath, modifiedData: Buffer.from( (await readFile()) .toString("utf8") .replace("top: -34px;", "top: -34px !important;"), "utf8" ) }); return; } } skip_unused_resources: { if (keycloakVersion !== KEYCLOAK_VERSION.FOR_LOGIN_THEME) { break skip_unused_resources; } skip_node_modules: { const nodeModulesRelativeDirPath = pathJoin( "keycloak", "common", "resources", "node_modules" ); if (!fileRelativePath.startsWith(nodeModulesRelativeDirPath)) { break skip_node_modules; } if (kcNodeModulesKeepFilePaths === undefined) { kcNodeModulesKeepFilePaths = new Set([ pathJoin("@patternfly", "patternfly", "patternfly.min.css"), pathJoin("patternfly", "dist", "css", "patternfly.min.css"), pathJoin( "patternfly", "dist", "css", "patternfly-additions.min.css" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Regular-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Light-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Bold-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Bold-webfont.woff" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Bold-webfont.ttf" ), pathJoin( "patternfly", "dist", "fonts", "fontawesome-webfont.woff2" ), pathJoin( "patternfly", "dist", "fonts", "PatternFlyIcons-webfont.ttf" ), pathJoin( "patternfly", "dist", "fonts", "PatternFlyIcons-webfont.woff" ), pathJoin( "patternfly", "dist", "fonts", "OpenSans-Semibold-webfont.woff2" ), pathJoin("patternfly", "dist", "img", "bg-login.jpg"), pathJoin("jquery", "dist", "jquery.min.js"), pathJoin("rfc4648", "lib", "rfc4648.js") ]); } const fileRelativeToNodeModulesPath = fileRelativePath.substring( nodeModulesRelativeDirPath.length + 1 ); if (kcNodeModulesKeepFilePaths.has(fileRelativeToNodeModulesPath)) { break skip_node_modules; } return; } skip_vendor: { if ( !fileRelativePath.startsWith( pathJoin("keycloak", "common", "resources", "vendor") ) ) { break skip_vendor; } return; } skip_rollup_config: { if ( fileRelativePath !== pathJoin("keycloak", "common", "resources", "rollup.config.js") ) { break skip_rollup_config; } return; } skip_package_json: { if ( fileRelativePath !== pathJoin("keycloak", "common", "resources", "package.json") ) { break skip_package_json; } return; } } await writeFile({ fileRelativePath }); } }); return { extractedDirPath }; }