Build retrocompatible account theme

This commit is contained in:
garronej 2023-09-04 02:16:55 +02:00
parent cd8548fc32
commit 28288a8f7b
6 changed files with 46 additions and 15 deletions

View File

@ -3,5 +3,7 @@ export const resources_common = "resources-common";
export const lastKeycloakVersionWithAccountV1 = "21.1.2"; export const lastKeycloakVersionWithAccountV1 = "21.1.2";
export const themeTypes = ["login", "account"] as const; export const themeTypes = ["login", "account"] as const;
export const retrocompatPostfix = "_retrocompat";
export const accountV1 = "account-v1";
export type ThemeType = (typeof themeTypes)[number]; export type ThemeType = (typeof themeTypes)[number];

View File

@ -24,6 +24,7 @@ export type BuildOptions = {
/** If your app is hosted under a subpath, it's the case in CRA if you have "homepage": "https://example.com/my-app" in your package.json /** If your app is hosted under a subpath, it's the case in CRA if you have "homepage": "https://example.com/my-app" in your package.json
* In this case the urlPathname will be "/my-app/" */ * In this case the urlPathname will be "/my-app/" */
urlPathname: string | undefined; urlPathname: string | undefined;
doBuildRetrocompatAccountTheme: boolean;
}; };
export function readBuildOptions(params: { reactAppRootDirPath: string; processArgv: string[] }): BuildOptions { export function readBuildOptions(params: { reactAppRootDirPath: string; processArgv: string[] }): BuildOptions {
@ -150,6 +151,7 @@ export function readBuildOptions(params: { reactAppRootDirPath: string; processA
const out = url.pathname.replace(/([^/])$/, "$1/"); const out = url.pathname.replace(/([^/])$/, "$1/");
return out === "/" ? undefined : out; return out === "/" ? undefined : out;
})() })(),
"doBuildRetrocompatAccountTheme": parsedPackageJson.keycloakify?.doBuildRetrocompatAccountTheme ?? true
}; };
} }

View File

@ -3,7 +3,7 @@ import { join as pathJoin, dirname as pathDirname } from "path";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { Reflect } from "tsafe/Reflect"; import { Reflect } from "tsafe/Reflect";
import type { BuildOptions } from "../BuildOptions"; import type { BuildOptions } from "../BuildOptions";
import { resources_common, lastKeycloakVersionWithAccountV1 } from "../../constants"; import { resources_common, lastKeycloakVersionWithAccountV1, accountV1 } from "../../constants";
import { downloadBuiltinKeycloakTheme } from "../../download-builtin-keycloak-theme"; import { downloadBuiltinKeycloakTheme } from "../../download-builtin-keycloak-theme";
import { transformCodebase } from "../../tools/transformCodebase"; import { transformCodebase } from "../../tools/transformCodebase";
@ -18,8 +18,6 @@ export type BuildOptionsLike = {
assert<typeof buildOptions extends BuildOptionsLike ? true : false>(); assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
} }
export const accountV1 = "account-v1";
export async function bringInAccountV1(params: { buildOptions: BuildOptionsLike }) { export async function bringInAccountV1(params: { buildOptions: BuildOptionsLike }) {
const { buildOptions } = params; const { buildOptions } = params;

View File

@ -3,8 +3,8 @@ import { join as pathJoin, dirname as pathDirname } from "path";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { Reflect } from "tsafe/Reflect"; import { Reflect } from "tsafe/Reflect";
import type { BuildOptions } from "../BuildOptions"; import type { BuildOptions } from "../BuildOptions";
import { type ThemeType } from "../../constants"; import { type ThemeType, retrocompatPostfix, accountV1 } from "../../constants";
import { bringInAccountV1, accountV1 } from "./bringInAccountV1"; import { bringInAccountV1 } from "./bringInAccountV1";
export type BuildOptionsLike = { export type BuildOptionsLike = {
groupId: string; groupId: string;
@ -189,7 +189,7 @@ export async function generateJavaStackFiles(params: {
? [] ? []
: [ : [
{ {
"name": `${themeName}_retrocompat`, "name": `${themeName}${retrocompatPostfix}`,
"types": ["account"] "types": ["account"]
} }
]) ])

View File

@ -1,10 +1,10 @@
import { transformCodebase } from "../../tools/transformCodebase"; import { transformCodebase } from "../../tools/transformCodebase";
import * as fs from "fs"; import * as fs from "fs";
import { join as pathJoin } from "path"; import { join as pathJoin, basename as pathBasename } from "path";
import { replaceImportsFromStaticInJsCode } from "../replacers/replaceImportsFromStaticInJsCode"; import { replaceImportsFromStaticInJsCode } from "../replacers/replaceImportsFromStaticInJsCode";
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode"; import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds } from "../generateFtl"; import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds } from "../generateFtl";
import { themeTypes, type ThemeType, lastKeycloakVersionWithAccountV1, keycloak_resources } from "../../constants"; import { themeTypes, type ThemeType, lastKeycloakVersionWithAccountV1, keycloak_resources, retrocompatPostfix, accountV1 } from "../../constants";
import { isInside } from "../../tools/isInside"; import { isInside } from "../../tools/isInside";
import type { BuildOptions } from "../BuildOptions"; import type { BuildOptions } from "../BuildOptions";
import { assert, type Equals } from "tsafe/assert"; import { assert, type Equals } from "tsafe/assert";
@ -22,6 +22,7 @@ export type BuildOptionsLike = {
keycloakifyBuildDirPath: string; keycloakifyBuildDirPath: string;
reactAppBuildDirPath: string; reactAppBuildDirPath: string;
cacheDirPath: string; cacheDirPath: string;
doBuildRetrocompatAccountTheme: boolean;
}; };
assert<BuildOptions extends BuildOptionsLike ? true : false>(); assert<BuildOptions extends BuildOptionsLike ? true : false>();
@ -35,8 +36,18 @@ export async function generateTheme(params: {
}): Promise<void> { }): Promise<void> {
const { themeName, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params; const { themeName, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params;
const getThemeDirPath = (themeType: ThemeType | "email") => const getThemeDirPath = (params: { themeType: ThemeType | "email"; isRetrocompat?: true }) => {
pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme", themeName, themeType); const { themeType, isRetrocompat = false } = params;
return pathJoin(
buildOptions.keycloakifyBuildDirPath,
"src",
"main",
"resources",
"theme",
`${themeName}${isRetrocompat ? retrocompatPostfix : ""}`,
themeType
);
};
let allCssGlobalsToDefine: Record<string, string> = {}; let allCssGlobalsToDefine: Record<string, string> = {};
@ -47,7 +58,7 @@ export async function generateTheme(params: {
continue; continue;
} }
const themeDirPath = getThemeDirPath(themeType); const themeDirPath = getThemeDirPath({ themeType });
copy_app_resources_to_theme_path: { copy_app_resources_to_theme_path: {
const isFirstPass = themeType.indexOf(themeType) === 0; const isFirstPass = themeType.indexOf(themeType) === 0;
@ -179,7 +190,7 @@ export async function generateTheme(params: {
`parent=${(() => { `parent=${(() => {
switch (themeType) { switch (themeType) {
case "account": case "account":
return "account-v1"; return accountV1;
case "login": case "login":
return "keycloak"; return "keycloak";
} }
@ -190,6 +201,22 @@ export async function generateTheme(params: {
"utf8" "utf8"
) )
); );
if (themeType === "account" && buildOptions.doBuildRetrocompatAccountTheme) {
transformCodebase({
"srcDirPath": themeDirPath,
"destDirPath": getThemeDirPath({ themeType, "isRetrocompat": true }),
"transformSourceCode": ({ filePath, sourceCode }) => {
if (pathBasename(filePath) === "theme.properties") {
return {
"modifiedSourceCode": Buffer.from(sourceCode.toString("utf8").replace(`parent=${accountV1}`, "parent=keycloak"), "utf8")
};
}
return { "modifiedSourceCode": sourceCode };
}
});
}
} }
email: { email: {
@ -201,7 +228,7 @@ export async function generateTheme(params: {
transformCodebase({ transformCodebase({
"srcDirPath": emailThemeSrcDirPath, "srcDirPath": emailThemeSrcDirPath,
"destDirPath": getThemeDirPath("email") "destDirPath": getThemeDirPath({ "themeType": "email" })
}); });
} }
} }

View File

@ -18,6 +18,7 @@ export type ParsedPackageJson = {
reactAppBuildDirPath?: string; reactAppBuildDirPath?: string;
keycloakifyBuildDirPath?: string; keycloakifyBuildDirPath?: string;
themeName?: string | string[]; themeName?: string | string[];
doBuildRetrocompatAccountTheme?: boolean;
}; };
}; };
@ -35,7 +36,8 @@ export const zParsedPackageJson = z.object({
"loginThemeResourcesFromKeycloakVersion": z.string().optional(), "loginThemeResourcesFromKeycloakVersion": z.string().optional(),
"reactAppBuildDirPath": z.string().optional(), "reactAppBuildDirPath": z.string().optional(),
"keycloakifyBuildDirPath": z.string().optional(), "keycloakifyBuildDirPath": z.string().optional(),
"themeName": z.union([z.string(), z.array(z.string())]).optional() "themeName": z.union([z.string(), z.array(z.string())]).optional(),
"doBuildRetrocompatAccountTheme": z.boolean().optional()
}) })
.optional() .optional()
}); });