Implement generateThemeVariants

This commit is contained in:
Joseph Garrone 2024-05-12 21:23:20 +02:00
parent 5a7d452429
commit 824076f730
6 changed files with 73 additions and 44 deletions

View File

@ -5,12 +5,12 @@ import { getKeycloakVersionRangeForJar } from "./getKeycloakVersionRangeForJar";
import { buildJar } from "./buildJar"; import { buildJar } from "./buildJar";
export async function buildJars(params: { export async function buildJars(params: {
doImplementAccountTheme: boolean; doesImplementAccountTheme: boolean;
buildOptions: { buildOptions: {
keycloakifyBuildDirPath: string; keycloakifyBuildDirPath: string;
}; };
}): Promise<{ lastJarFileBasename: string }> { }): Promise<{ lastJarFileBasename: string }> {
const { doImplementAccountTheme, buildOptions } = params; const { doesImplementAccountTheme, buildOptions } = params;
let lastJarFileBasename: string | undefined = undefined; let lastJarFileBasename: string | undefined = undefined;
@ -20,7 +20,7 @@ export async function buildJars(params: {
keycloakThemeAdditionalInfoExtensionVersions keycloakThemeAdditionalInfoExtensionVersions
.map(keycloakThemeAdditionalInfoExtensionVersion => { .map(keycloakThemeAdditionalInfoExtensionVersion => {
const keycloakVersionRange = getKeycloakVersionRangeForJar({ const keycloakVersionRange = getKeycloakVersionRangeForJar({
doImplementAccountTheme, doesImplementAccountTheme,
keycloakAccountV1Version, keycloakAccountV1Version,
keycloakThemeAdditionalInfoExtensionVersion keycloakThemeAdditionalInfoExtensionVersion
}); });

View File

@ -2,35 +2,35 @@ import { assert, type Equals } from "tsafe/assert";
import type { KeycloakAccountV1Versions, KeycloakThemeAdditionalInfoExtensionVersions } from "./extensionVersions"; import type { KeycloakAccountV1Versions, KeycloakThemeAdditionalInfoExtensionVersions } from "./extensionVersions";
export function getKeycloakVersionRangeForJar(params: { export function getKeycloakVersionRangeForJar(params: {
doImplementAccountTheme: boolean; doesImplementAccountTheme: boolean;
keycloakAccountV1Version: KeycloakAccountV1Versions; keycloakAccountV1Version: KeycloakAccountV1Versions;
keycloakThemeAdditionalInfoExtensionVersion: KeycloakThemeAdditionalInfoExtensionVersions; keycloakThemeAdditionalInfoExtensionVersion: KeycloakThemeAdditionalInfoExtensionVersions;
}): string | undefined { }): string | undefined {
const { keycloakAccountV1Version, keycloakThemeAdditionalInfoExtensionVersion, doImplementAccountTheme } = params; const { keycloakAccountV1Version, keycloakThemeAdditionalInfoExtensionVersion, doesImplementAccountTheme } = params;
switch (keycloakAccountV1Version) { switch (keycloakAccountV1Version) {
case null: case null:
switch (keycloakThemeAdditionalInfoExtensionVersion) { switch (keycloakThemeAdditionalInfoExtensionVersion) {
case null: case null:
return doImplementAccountTheme ? "21-and-below" : "21-and-below"; return doesImplementAccountTheme ? "21-and-below" : "21-and-below";
case "0.1": case "0.1":
return doImplementAccountTheme ? undefined : "22-and-above"; return doesImplementAccountTheme ? undefined : "22-and-above";
} }
assert<Equals<typeof keycloakThemeAdditionalInfoExtensionVersion, never>>(false); assert<Equals<typeof keycloakThemeAdditionalInfoExtensionVersion, never>>(false);
case "0.3": case "0.3":
switch (keycloakThemeAdditionalInfoExtensionVersion) { switch (keycloakThemeAdditionalInfoExtensionVersion) {
case null: case null:
return doImplementAccountTheme ? undefined : undefined; return doesImplementAccountTheme ? undefined : undefined;
case "0.1": case "0.1":
return doImplementAccountTheme ? "23" : undefined; return doesImplementAccountTheme ? "23" : undefined;
} }
assert<Equals<typeof keycloakThemeAdditionalInfoExtensionVersion, never>>(false); assert<Equals<typeof keycloakThemeAdditionalInfoExtensionVersion, never>>(false);
case "0.4": case "0.4":
switch (keycloakThemeAdditionalInfoExtensionVersion) { switch (keycloakThemeAdditionalInfoExtensionVersion) {
case null: case null:
return doImplementAccountTheme ? undefined : undefined; return doesImplementAccountTheme ? undefined : undefined;
case "0.1": case "0.1":
return doImplementAccountTheme ? "24-and-above" : undefined; return doesImplementAccountTheme ? "24-and-above" : undefined;
} }
assert<Equals<typeof keycloakThemeAdditionalInfoExtensionVersion, never>>(false); assert<Equals<typeof keycloakThemeAdditionalInfoExtensionVersion, never>>(false);
} }

View File

@ -42,7 +42,7 @@ export async function generateSrcMainResources(params: {
buildOptions: BuildOptionsLike; buildOptions: BuildOptionsLike;
keycloakifyVersion: string; keycloakifyVersion: string;
srcMainResourcesDirPath: string; srcMainResourcesDirPath: string;
}): Promise<{ implementedThemeTypes: Record<ThemeType | "email", boolean> }> { }): Promise<{ doesImplementAccountTheme: boolean }> {
const { themeName, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion, srcMainResourcesDirPath } = params; const { themeName, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion, srcMainResourcesDirPath } = params;
const getThemeTypeDirPath = (params: { themeType: ThemeType | "email" }) => { const getThemeTypeDirPath = (params: { themeType: ThemeType | "email" }) => {
@ -263,5 +263,5 @@ export async function generateSrcMainResources(params: {
fs.writeFileSync(keycloakThemeJsonFilePath, Buffer.from(JSON.stringify(parsedKeycloakThemeJson, null, 2), "utf8")); fs.writeFileSync(keycloakThemeJsonFilePath, Buffer.from(JSON.stringify(parsedKeycloakThemeJson, null, 2), "utf8"));
} }
return { implementedThemeTypes }; return { "doesImplementAccountTheme": implementedThemeTypes.account };
} }

View File

@ -1,22 +1,12 @@
import { type ThemeType } from "../../constants";
import { join as pathJoin } from "path"; import { join as pathJoin } from "path";
import type { BuildOptions } from "../buildOptions"; import type { BuildOptions } from "../buildOptions";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { generateSrcMainResources } from "./generateSrcMainResources"; import { generateSrcMainResources, type BuildOptionsLike as BuildOptionsLike_generateSrcMainResources } from "./generateSrcMainResources";
import { generateThemeVariations } from "./generateThemeVariants"; import { generateThemeVariations } from "./generateThemeVariants";
export type BuildOptionsLike = { export type BuildOptionsLike = BuildOptionsLike_generateSrcMainResources & {
bundler: "vite" | "webpack";
themeNames: string[];
extraThemeProperties: string[] | undefined;
themeVersion: string;
loginThemeResourcesFromKeycloakVersion: string;
keycloakifyBuildDirPath: string; keycloakifyBuildDirPath: string;
reactAppBuildDirPath: string; themeNames: string[];
cacheDirPath: string;
assetsDirPath: string;
urlPathname: string | undefined;
npmWorkspaceRootDirPath: string;
}; };
assert<BuildOptions extends BuildOptionsLike ? true : false>(); assert<BuildOptions extends BuildOptionsLike ? true : false>();
@ -26,14 +16,16 @@ export async function generateTheme(params: {
keycloakifySrcDirPath: string; keycloakifySrcDirPath: string;
buildOptions: BuildOptionsLike; buildOptions: BuildOptionsLike;
keycloakifyVersion: string; keycloakifyVersion: string;
}): Promise<{ implementedThemeTypes: Record<ThemeType | "email", boolean> }> { }): Promise<{ doesImplementAccountTheme: boolean }> {
const { themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params; const { themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params;
const [themeName, ...themeVariantNames] = buildOptions.themeNames; const [themeName, ...themeVariantNames] = buildOptions.themeNames;
const { implementedThemeTypes } = await generateSrcMainResources({ const srcMainResourcesDirPath = pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources");
const { doesImplementAccountTheme } = await generateSrcMainResources({
themeName, themeName,
"srcMainResourcesDirPath": pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources"), srcMainResourcesDirPath,
themeSrcDirPath, themeSrcDirPath,
keycloakifySrcDirPath, keycloakifySrcDirPath,
keycloakifyVersion, keycloakifyVersion,
@ -44,10 +36,9 @@ export async function generateTheme(params: {
generateThemeVariations({ generateThemeVariations({
themeName, themeName,
themeVariantName, themeVariantName,
implementedThemeTypes, srcMainResourcesDirPath
buildOptions
}); });
} }
return { implementedThemeTypes }; return { doesImplementAccountTheme };
} }

View File

@ -1,12 +1,50 @@
import type { ThemeType } from "../../constants"; import { join as pathJoin, extname as pathExtname, sep as pathSep } from "path";
import { transformCodebase } from "../../tools/transformCodebase";
import { assert } from "tsafe/assert";
import * as fs from "fs";
export function generateThemeVariations(params: { export function generateThemeVariations(params: { themeName: string; themeVariantName: string; srcMainResourcesDirPath: string }) {
themeName: string; const { themeName, themeVariantName, srcMainResourcesDirPath } = params;
themeVariantName: string;
implementedThemeTypes: Record<ThemeType | "email", boolean>; const mainThemeDirPath = pathJoin(srcMainResourcesDirPath, "theme", themeName);
buildOptions: {
keycloakifyBuildDirPath: string; transformCodebase({
}; "srcDirPath": mainThemeDirPath,
}) { "destDirPath": pathJoin(mainThemeDirPath, themeVariantName),
//TODO: Implement "transformSourceCode": ({ fileRelativePath, sourceCode }) => {
if (pathExtname(fileRelativePath) === ".ftl" && fileRelativePath.split(pathSep).length === 2) {
const modifiedSourceCode = Buffer.from(
Buffer.from(sourceCode)
.toString("utf-8")
.replace(`out["themeName"] = "${themeName}";`, `out["themeName"] = "${themeVariantName}";`),
"utf8"
);
assert(Buffer.compare(modifiedSourceCode, sourceCode) !== 0);
return { modifiedSourceCode };
}
return { "modifiedSourceCode": sourceCode };
}
});
{
const keycloakThemeJsonFilePath = pathJoin(srcMainResourcesDirPath, "META-INF", "keycloak-themes.json");
const modifiedParsedJson = JSON.parse(fs.readFileSync(keycloakThemeJsonFilePath).toString("utf8")) as {
themes: { name: string; types: string[] }[];
};
modifiedParsedJson.themes.push({
"name": themeVariantName,
"types": (() => {
const theme = modifiedParsedJson.themes.find(({ name }) => name === themeName);
assert(theme !== undefined);
return theme.types;
})()
});
fs.writeFileSync(keycloakThemeJsonFilePath, Buffer.from(JSON.stringify(modifiedParsedJson, null, 2), "utf8"));
}
} }

View File

@ -29,7 +29,7 @@ export async function main() {
fs.writeFileSync(pathJoin(buildOptions.keycloakifyBuildDirPath, ".gitignore"), Buffer.from("*", "utf8")); fs.writeFileSync(pathJoin(buildOptions.keycloakifyBuildDirPath, ".gitignore"), Buffer.from("*", "utf8"));
} }
const { implementedThemeTypes } = await generateTheme({ const { doesImplementAccountTheme } = await generateTheme({
themeSrcDirPath, themeSrcDirPath,
"keycloakifySrcDirPath": pathJoin(getThisCodebaseRootDirPath(), "src"), "keycloakifySrcDirPath": pathJoin(getThisCodebaseRootDirPath(), "src"),
"keycloakifyVersion": readThisNpmProjectVersion(), "keycloakifyVersion": readThisNpmProjectVersion(),
@ -51,7 +51,7 @@ export async function main() {
} }
const { lastJarFileBasename } = await buildJars({ const { lastJarFileBasename } = await buildJars({
"doImplementAccountTheme": implementedThemeTypes.account, doesImplementAccountTheme,
buildOptions buildOptions
}); });