Refactor how we update META-INF and how we read what theme types are implemented
This commit is contained in:
parent
9e70e5c12e
commit
61fbbb0b09
@ -16,7 +16,7 @@ import { readFileSync } from "fs";
|
|||||||
import { isInside } from "../../tools/isInside";
|
import { isInside } from "../../tools/isInside";
|
||||||
import child_process from "child_process";
|
import child_process from "child_process";
|
||||||
import { rmSync } from "../../tools/fs.rmSync";
|
import { rmSync } from "../../tools/fs.rmSync";
|
||||||
import { getMetaInfKeycloakThemesJsonFilePath } from "../../shared/metaInfKeycloakThemes";
|
import { writeMetaInfKeycloakThemes } from "../../shared/metaInfKeycloakThemes";
|
||||||
|
|
||||||
export type BuildContextLike = BuildContextLike_generatePom & {
|
export type BuildContextLike = BuildContextLike_generatePom & {
|
||||||
keycloakifyBuildDirPath: string;
|
keycloakifyBuildDirPath: string;
|
||||||
@ -50,9 +50,16 @@ export async function buildJar(params: {
|
|||||||
|
|
||||||
rmSync(keycloakifyBuildTmpDirPath, { recursive: true, force: true });
|
rmSync(keycloakifyBuildTmpDirPath, { recursive: true, force: true });
|
||||||
|
|
||||||
|
const tmpResourcesDirPath = pathJoin(
|
||||||
|
keycloakifyBuildTmpDirPath,
|
||||||
|
"src",
|
||||||
|
"main",
|
||||||
|
"resources"
|
||||||
|
);
|
||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
srcDirPath: resourcesDirPath,
|
srcDirPath: resourcesDirPath,
|
||||||
destDirPath: pathJoin(keycloakifyBuildTmpDirPath, "src", "main", "resources"),
|
destDirPath: tmpResourcesDirPath,
|
||||||
transformSourceCode:
|
transformSourceCode:
|
||||||
keycloakAccountV1Version !== null
|
keycloakAccountV1Version !== null
|
||||||
? undefined
|
? undefined
|
||||||
@ -71,31 +78,6 @@ export async function buildJar(params: {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
fileRelativePath ===
|
|
||||||
getMetaInfKeycloakThemesJsonFilePath({
|
|
||||||
resourcesDirPath: "."
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
const keycloakThemesJsonParsed = JSON.parse(
|
|
||||||
sourceCode.toString("utf8")
|
|
||||||
) as {
|
|
||||||
themes: { name: string; types: string[] }[];
|
|
||||||
};
|
|
||||||
|
|
||||||
keycloakThemesJsonParsed.themes =
|
|
||||||
keycloakThemesJsonParsed.themes.filter(
|
|
||||||
({ name }) => name !== accountV1ThemeName
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
modifiedSourceCode: Buffer.from(
|
|
||||||
JSON.stringify(keycloakThemesJsonParsed, null, 2),
|
|
||||||
"utf8"
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const themeName of buildContext.themeNames) {
|
for (const themeName of buildContext.themeNames) {
|
||||||
if (
|
if (
|
||||||
fileRelativePath ===
|
fileRelativePath ===
|
||||||
@ -123,6 +105,21 @@ export async function buildJar(params: {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (keycloakAccountV1Version === null) {
|
||||||
|
writeMetaInfKeycloakThemes({
|
||||||
|
resourcesDirPath: tmpResourcesDirPath,
|
||||||
|
getNewMetaInfKeycloakTheme: ({ metaInfKeycloakTheme }) => {
|
||||||
|
assert(metaInfKeycloakTheme !== undefined);
|
||||||
|
|
||||||
|
metaInfKeycloakTheme.themes = metaInfKeycloakTheme.themes.filter(
|
||||||
|
({ name }) => name !== accountV1ThemeName
|
||||||
|
);
|
||||||
|
|
||||||
|
return metaInfKeycloakTheme;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
route_legacy_pages: {
|
route_legacy_pages: {
|
||||||
// NOTE: If there's no account theme there is no special target for keycloak 24 and up so we create
|
// NOTE: If there's no account theme there is no special target for keycloak 24 and up so we create
|
||||||
// the pages anyway. If there is an account pages, since we know that account-v1 is only support keycloak
|
// the pages anyway. If there is an account pages, since we know that account-v1 is only support keycloak
|
||||||
|
@ -8,10 +8,10 @@ import { getKeycloakVersionRangeForJar } from "./getKeycloakVersionRangeForJar";
|
|||||||
import { buildJar, BuildContextLike as BuildContextLike_buildJar } from "./buildJar";
|
import { buildJar, BuildContextLike as BuildContextLike_buildJar } from "./buildJar";
|
||||||
import type { BuildContext } from "../../shared/buildContext";
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
import { getJarFileBasename } from "../../shared/getJarFileBasename";
|
import { getJarFileBasename } from "../../shared/getJarFileBasename";
|
||||||
import { readMetaInfKeycloakThemes_fromResourcesDirPath } from "../../shared/metaInfKeycloakThemes";
|
import { getImplementedThemeTypes } from "../../shared/getImplementedThemeTypes";
|
||||||
import { accountV1ThemeName } from "../../shared/constants";
|
|
||||||
|
|
||||||
export type BuildContextLike = BuildContextLike_buildJar & {
|
export type BuildContextLike = BuildContextLike_buildJar & {
|
||||||
|
projectDirPath: string;
|
||||||
keycloakifyBuildDirPath: string;
|
keycloakifyBuildDirPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ export async function buildJars(params: {
|
|||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const { onlyBuildJarFileBasename, resourcesDirPath, buildContext } = params;
|
const { onlyBuildJarFileBasename, resourcesDirPath, buildContext } = params;
|
||||||
|
|
||||||
const doesImplementAccountTheme = readMetaInfKeycloakThemes_fromResourcesDirPath({
|
const doesImplementAccountTheme = getImplementedThemeTypes({
|
||||||
resourcesDirPath
|
projectDirPath: buildContext.projectDirPath
|
||||||
}).themes.some(({ name }) => name === accountV1ThemeName);
|
}).implementedThemeTypes.account;
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
keycloakAccountV1Versions
|
keycloakAccountV1Versions
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { transformCodebase } from "../../tools/transformCodebase";
|
import { transformCodebase } from "../../tools/transformCodebase";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin, resolve as pathResolve } from "path";
|
import { join as pathJoin, resolve as pathResolve, relative as pathRelative } from "path";
|
||||||
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
|
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
|
||||||
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
||||||
import {
|
import {
|
||||||
@ -16,7 +16,6 @@ import {
|
|||||||
loginThemePageIds,
|
loginThemePageIds,
|
||||||
accountThemePageIds
|
accountThemePageIds
|
||||||
} from "../../shared/constants";
|
} from "../../shared/constants";
|
||||||
import { isInside } from "../../tools/isInside";
|
|
||||||
import type { BuildContext } from "../../shared/buildContext";
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
import {
|
import {
|
||||||
@ -39,6 +38,7 @@ import {
|
|||||||
} from "../../shared/metaInfKeycloakThemes";
|
} from "../../shared/metaInfKeycloakThemes";
|
||||||
import { objectEntries } from "tsafe/objectEntries";
|
import { objectEntries } from "tsafe/objectEntries";
|
||||||
import { escapeStringForPropertiesFile } from "../../tools/escapeStringForPropertiesFile";
|
import { escapeStringForPropertiesFile } from "../../tools/escapeStringForPropertiesFile";
|
||||||
|
import { getImplementedThemeTypes } from "../../shared/getImplementedThemeTypes";
|
||||||
|
|
||||||
export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode &
|
export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode &
|
||||||
BuildContextLike_downloadKeycloakStaticResources &
|
BuildContextLike_downloadKeycloakStaticResources &
|
||||||
@ -63,6 +63,10 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
projectDirPath: buildContext.projectDirPath
|
projectDirPath: buildContext.projectDirPath
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { implementedThemeTypes } = getImplementedThemeTypes({
|
||||||
|
projectDirPath: buildContext.projectDirPath
|
||||||
|
});
|
||||||
|
|
||||||
const getThemeTypeDirPath = (params: { themeType: ThemeType | "email" }) => {
|
const getThemeTypeDirPath = (params: { themeType: ThemeType | "email" }) => {
|
||||||
const { themeType } = params;
|
const { themeType } = params;
|
||||||
return pathJoin(resourcesDirPath, "theme", themeName, themeType);
|
return pathJoin(resourcesDirPath, "theme", themeName, themeType);
|
||||||
@ -70,19 +74,11 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
|
|
||||||
const cssGlobalsToDefine: Record<string, string> = {};
|
const cssGlobalsToDefine: Record<string, string> = {};
|
||||||
|
|
||||||
const implementedThemeTypes: Record<ThemeType | "email", boolean> = {
|
|
||||||
login: false,
|
|
||||||
account: false,
|
|
||||||
email: false
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const themeType of ["login", "account"] as const) {
|
for (const themeType of ["login", "account"] as const) {
|
||||||
if (!fs.existsSync(pathJoin(themeSrcDirPath, themeType))) {
|
if (!implementedThemeTypes[themeType]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
implementedThemeTypes[themeType] = true;
|
|
||||||
|
|
||||||
const themeTypeDirPath = getThemeTypeDirPath({ themeType });
|
const themeTypeDirPath = getThemeTypeDirPath({ themeType });
|
||||||
|
|
||||||
apply_replacers_and_move_to_theme_resources: {
|
apply_replacers_and_move_to_theme_resources: {
|
||||||
@ -112,25 +108,32 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
break apply_replacers_and_move_to_theme_resources;
|
break apply_replacers_and_move_to_theme_resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const dirPath = pathJoin(
|
||||||
|
buildContext.projectBuildDirPath,
|
||||||
|
keycloak_resources
|
||||||
|
);
|
||||||
|
|
||||||
|
if (fs.existsSync(dirPath)) {
|
||||||
|
assert(buildContext.bundler === "webpack");
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
`Keycloakify build error: The ${keycloak_resources} directory shouldn't exist in your build directory.`,
|
||||||
|
`(${pathRelative(process.cwd(), dirPath)}).\n`,
|
||||||
|
`Theses assets are only required for local development with Storybook.",
|
||||||
|
"Please remove this directory as an additional step of your command.\n`,
|
||||||
|
`For example: \`"build": "... && rimraf ${pathRelative(buildContext.projectDirPath, dirPath)}"\``
|
||||||
|
].join(" ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
srcDirPath: buildContext.projectBuildDirPath,
|
srcDirPath: buildContext.projectBuildDirPath,
|
||||||
destDirPath,
|
destDirPath,
|
||||||
transformSourceCode: ({ filePath, sourceCode }) => {
|
transformSourceCode: ({ filePath, sourceCode }) => {
|
||||||
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
if (filePath.endsWith(".css")) {
|
||||||
// This should not happen if users follow the new instruction setup but we keep it for retrocompatibility.
|
|
||||||
if (
|
|
||||||
isInside({
|
|
||||||
dirPath: pathJoin(
|
|
||||||
buildContext.projectBuildDirPath,
|
|
||||||
keycloak_resources
|
|
||||||
),
|
|
||||||
filePath
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/\.css?$/i.test(filePath)) {
|
|
||||||
const {
|
const {
|
||||||
cssGlobalsToDefine: cssGlobalsToDefineForThisFile,
|
cssGlobalsToDefine: cssGlobalsToDefineForThisFile,
|
||||||
fixedCssCode
|
fixedCssCode
|
||||||
@ -149,7 +152,7 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/\.js?$/i.test(filePath)) {
|
if (filePath.endsWith(".js")) {
|
||||||
const { fixedJsCode } = replaceImportsInJsCode({
|
const { fixedJsCode } = replaceImportsInJsCode({
|
||||||
jsCode: sourceCode.toString("utf8"),
|
jsCode: sourceCode.toString("utf8"),
|
||||||
buildContext
|
buildContext
|
||||||
@ -262,13 +265,11 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
email: {
|
email: {
|
||||||
const emailThemeSrcDirPath = pathJoin(themeSrcDirPath, "email");
|
if (!implementedThemeTypes.email) {
|
||||||
|
|
||||||
if (!fs.existsSync(emailThemeSrcDirPath)) {
|
|
||||||
break email;
|
break email;
|
||||||
}
|
}
|
||||||
|
|
||||||
implementedThemeTypes.email = true;
|
const emailThemeSrcDirPath = pathJoin(themeSrcDirPath, "email");
|
||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
srcDirPath: emailThemeSrcDirPath,
|
srcDirPath: emailThemeSrcDirPath,
|
||||||
@ -302,7 +303,7 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
|
|
||||||
writeMetaInfKeycloakThemes({
|
writeMetaInfKeycloakThemes({
|
||||||
resourcesDirPath,
|
resourcesDirPath,
|
||||||
metaInfKeycloakThemes
|
getNewMetaInfKeycloakTheme: () => metaInfKeycloakThemes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { join as pathJoin, extname as pathExtname, sep as pathSep } from "path";
|
import { join as pathJoin, extname as pathExtname, sep as pathSep } from "path";
|
||||||
import { transformCodebase } from "../../tools/transformCodebase";
|
import { transformCodebase } from "../../tools/transformCodebase";
|
||||||
import type { BuildContext } from "../../shared/buildContext";
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
import {
|
import { writeMetaInfKeycloakThemes } from "../../shared/metaInfKeycloakThemes";
|
||||||
readMetaInfKeycloakThemes_fromResourcesDirPath,
|
|
||||||
writeMetaInfKeycloakThemes
|
|
||||||
} from "../../shared/metaInfKeycloakThemes";
|
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
|
|
||||||
export type BuildContextLike = {
|
export type BuildContextLike = {
|
||||||
@ -34,8 +31,8 @@ export function generateResourcesForThemeVariant(params: {
|
|||||||
Buffer.from(sourceCode)
|
Buffer.from(sourceCode)
|
||||||
.toString("utf-8")
|
.toString("utf-8")
|
||||||
.replace(
|
.replace(
|
||||||
`out["themeName"] = "${themeName}";`,
|
`kcContext.themeName = "${themeName}";`,
|
||||||
`out["themeName"] = "${themeVariantName}";`
|
`kcContext.themeName = "${themeVariantName}";`
|
||||||
),
|
),
|
||||||
"utf8"
|
"utf8"
|
||||||
);
|
);
|
||||||
@ -49,16 +46,17 @@ export function generateResourcesForThemeVariant(params: {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
writeMetaInfKeycloakThemes({
|
||||||
const updatedMetaInfKeycloakThemes =
|
resourcesDirPath,
|
||||||
readMetaInfKeycloakThemes_fromResourcesDirPath({
|
getNewMetaInfKeycloakTheme: ({ metaInfKeycloakTheme }) => {
|
||||||
resourcesDirPath
|
assert(metaInfKeycloakTheme !== undefined);
|
||||||
});
|
|
||||||
|
|
||||||
updatedMetaInfKeycloakThemes.themes.push({
|
const newMetaInfKeycloakTheme = metaInfKeycloakTheme;
|
||||||
|
|
||||||
|
newMetaInfKeycloakTheme.themes.push({
|
||||||
name: themeVariantName,
|
name: themeVariantName,
|
||||||
types: (() => {
|
types: (() => {
|
||||||
const theme = updatedMetaInfKeycloakThemes.themes.find(
|
const theme = newMetaInfKeycloakTheme.themes.find(
|
||||||
({ name }) => name === themeName
|
({ name }) => name === themeName
|
||||||
);
|
);
|
||||||
assert(theme !== undefined);
|
assert(theme !== undefined);
|
||||||
@ -66,9 +64,7 @@ export function generateResourcesForThemeVariant(params: {
|
|||||||
})()
|
})()
|
||||||
});
|
});
|
||||||
|
|
||||||
writeMetaInfKeycloakThemes({
|
return newMetaInfKeycloakTheme;
|
||||||
resourcesDirPath,
|
}
|
||||||
metaInfKeycloakThemes: updatedMetaInfKeycloakThemes
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
23
src/bin/shared/getImplementedThemeTypes.ts
Normal file
23
src/bin/shared/getImplementedThemeTypes.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { join as pathJoin } from "path";
|
||||||
|
import { objectFromEntries } from "tsafe/objectFromEntries";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { type ThemeType } from "./constants";
|
||||||
|
import { getThemeSrcDirPath } from "./getThemeSrcDirPath";
|
||||||
|
|
||||||
|
export function getImplementedThemeTypes(params: { projectDirPath: string }) {
|
||||||
|
const { projectDirPath } = params;
|
||||||
|
|
||||||
|
const { themeSrcDirPath } = getThemeSrcDirPath({
|
||||||
|
projectDirPath
|
||||||
|
});
|
||||||
|
|
||||||
|
const implementedThemeTypes: Readonly<Record<ThemeType | "email", boolean>> =
|
||||||
|
objectFromEntries(
|
||||||
|
(["login", "account", "email"] as const).map(themeType => [
|
||||||
|
themeType,
|
||||||
|
fs.existsSync(pathJoin(themeSrcDirPath, themeType))
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
return { implementedThemeTypes };
|
||||||
|
}
|
@ -3,13 +3,22 @@ import { exclude } from "tsafe";
|
|||||||
import { crawl } from "../tools/crawl";
|
import { crawl } from "../tools/crawl";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import { themeTypes } from "./constants";
|
import { themeTypes } from "./constants";
|
||||||
|
import chalk from "chalk";
|
||||||
|
|
||||||
const themeSrcDirBasenames = ["keycloak-theme", "keycloak_theme"];
|
let cache: { projectDirPath: string; themeSrcDirPath: string } | undefined = undefined;
|
||||||
|
|
||||||
/** Can't catch error, if the directory isn't found, this function will just exit the process with an error message. */
|
/** Can't catch error, if the directory isn't found, this function will just exit the process with an error message. */
|
||||||
export function getThemeSrcDirPath(params: { projectDirPath: string }) {
|
export function getThemeSrcDirPath(params: { projectDirPath: string }) {
|
||||||
const { projectDirPath } = params;
|
const { projectDirPath } = params;
|
||||||
|
|
||||||
|
if (cache !== undefined && cache.projectDirPath === projectDirPath) {
|
||||||
|
const { themeSrcDirPath } = cache;
|
||||||
|
return { themeSrcDirPath };
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = undefined;
|
||||||
|
|
||||||
|
const { themeSrcDirPath } = (() => {
|
||||||
const srcDirPath = pathJoin(projectDirPath, "src");
|
const srcDirPath = pathJoin(projectDirPath, "src");
|
||||||
|
|
||||||
const themeSrcDirPath: string | undefined = crawl({
|
const themeSrcDirPath: string | undefined = crawl({
|
||||||
@ -38,13 +47,16 @@ export function getThemeSrcDirPath(params: { projectDirPath: string }) {
|
|||||||
return { themeSrcDirPath: srcDirPath };
|
return { themeSrcDirPath: srcDirPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(
|
console.log(
|
||||||
[
|
chalk.red("Can't locate your theme source directory. It should be either: ")
|
||||||
"Can't locate your theme source directory. It should be either: ",
|
|
||||||
"src/ or src/keycloak-theme or src/keycloak_theme.",
|
|
||||||
"Example in the starter: https://github.com/keycloakify/keycloakify-starter/tree/main/src/keycloak-theme"
|
|
||||||
].join("\n")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
|
})();
|
||||||
|
|
||||||
|
cache = { projectDirPath, themeSrcDirPath };
|
||||||
|
|
||||||
|
return { themeSrcDirPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const themeSrcDirBasenames = ["keycloak-theme", "keycloak_theme"];
|
||||||
|
@ -1,84 +1,40 @@
|
|||||||
import { join as pathJoin, dirname as pathDirname } from "path";
|
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||||
import type { ThemeType } from "./constants";
|
import type { ThemeType } from "./constants";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { assert } from "tsafe/assert";
|
|
||||||
import { extractArchive } from "../tools/extractArchive";
|
|
||||||
|
|
||||||
export type MetaInfKeycloakTheme = {
|
export type MetaInfKeycloakTheme = {
|
||||||
themes: { name: string; types: (ThemeType | "email")[] }[];
|
themes: { name: string; types: (ThemeType | "email")[] }[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getMetaInfKeycloakThemesJsonFilePath(params: {
|
|
||||||
resourcesDirPath: string;
|
|
||||||
}) {
|
|
||||||
const { resourcesDirPath } = params;
|
|
||||||
|
|
||||||
return pathJoin(
|
|
||||||
resourcesDirPath === "." ? "" : resourcesDirPath,
|
|
||||||
"META-INF",
|
|
||||||
"keycloak-themes.json"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readMetaInfKeycloakThemes_fromResourcesDirPath(params: {
|
|
||||||
resourcesDirPath: string;
|
|
||||||
}) {
|
|
||||||
const { resourcesDirPath } = params;
|
|
||||||
|
|
||||||
return JSON.parse(
|
|
||||||
fs
|
|
||||||
.readFileSync(
|
|
||||||
getMetaInfKeycloakThemesJsonFilePath({
|
|
||||||
resourcesDirPath
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.toString("utf8")
|
|
||||||
) as MetaInfKeycloakTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function readMetaInfKeycloakThemes_fromJar(params: {
|
|
||||||
jarFilePath: string;
|
|
||||||
}): Promise<MetaInfKeycloakTheme> {
|
|
||||||
const { jarFilePath } = params;
|
|
||||||
let metaInfKeycloakThemes: MetaInfKeycloakTheme | undefined = undefined;
|
|
||||||
|
|
||||||
await extractArchive({
|
|
||||||
archiveFilePath: jarFilePath,
|
|
||||||
onArchiveFile: async ({ relativeFilePathInArchive, readFile, earlyExit }) => {
|
|
||||||
if (
|
|
||||||
relativeFilePathInArchive ===
|
|
||||||
getMetaInfKeycloakThemesJsonFilePath({ resourcesDirPath: "." })
|
|
||||||
) {
|
|
||||||
metaInfKeycloakThemes = JSON.parse((await readFile()).toString("utf8"));
|
|
||||||
earlyExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
assert(metaInfKeycloakThemes !== undefined);
|
|
||||||
|
|
||||||
return metaInfKeycloakThemes;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function writeMetaInfKeycloakThemes(params: {
|
export function writeMetaInfKeycloakThemes(params: {
|
||||||
resourcesDirPath: string;
|
resourcesDirPath: string;
|
||||||
metaInfKeycloakThemes: MetaInfKeycloakTheme;
|
getNewMetaInfKeycloakTheme: (params: {
|
||||||
|
metaInfKeycloakTheme: MetaInfKeycloakTheme | undefined;
|
||||||
|
}) => MetaInfKeycloakTheme;
|
||||||
}) {
|
}) {
|
||||||
const { resourcesDirPath, metaInfKeycloakThemes } = params;
|
const { resourcesDirPath, getNewMetaInfKeycloakTheme } = params;
|
||||||
|
|
||||||
const metaInfKeycloakThemesJsonPath = getMetaInfKeycloakThemesJsonFilePath({
|
const filePath = pathJoin(resourcesDirPath, "META-INF", "keycloak-themes.json");
|
||||||
resourcesDirPath
|
|
||||||
|
const currentMetaInfKeycloakTheme = !fs.existsSync(filePath)
|
||||||
|
? undefined
|
||||||
|
: (JSON.parse(
|
||||||
|
fs.readFileSync(filePath).toString("utf8")
|
||||||
|
) as MetaInfKeycloakTheme);
|
||||||
|
|
||||||
|
const newMetaInfKeycloakThemes = getNewMetaInfKeycloakTheme({
|
||||||
|
metaInfKeycloakTheme: currentMetaInfKeycloakTheme
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
const dirPath = pathDirname(metaInfKeycloakThemesJsonPath);
|
const dirPath = pathDirname(filePath);
|
||||||
if (!fs.existsSync(dirPath)) {
|
if (!fs.existsSync(dirPath)) {
|
||||||
fs.mkdirSync(dirPath, { recursive: true });
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
metaInfKeycloakThemesJsonPath,
|
filePath,
|
||||||
Buffer.from(JSON.stringify(metaInfKeycloakThemes, null, 2), "utf8")
|
Buffer.from(JSON.stringify(newMetaInfKeycloakThemes, null, 2), "utf8")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { getBuildContext } from "../shared/buildContext";
|
|||||||
import { exclude } from "tsafe/exclude";
|
import { exclude } from "tsafe/exclude";
|
||||||
import type { CliCommandOptions as CliCommandOptions_common } from "../main";
|
import type { CliCommandOptions as CliCommandOptions_common } from "../main";
|
||||||
import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
|
import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
|
||||||
import { readMetaInfKeycloakThemes_fromJar } from "../shared/metaInfKeycloakThemes";
|
import { getImplementedThemeTypes } from "../shared/getImplementedThemeTypes";
|
||||||
import { accountV1ThemeName, containerName } from "../shared/constants";
|
import { accountV1ThemeName, containerName } from "../shared/constants";
|
||||||
import { SemVer } from "../tools/SemVer";
|
import { SemVer } from "../tools/SemVer";
|
||||||
import type { KeycloakVersionRange } from "../shared/KeycloakVersionRange";
|
import type { KeycloakVersionRange } from "../shared/KeycloakVersionRange";
|
||||||
@ -120,37 +120,12 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { doesImplementAccountTheme } = await (async () => {
|
const doesImplementAccountTheme = getImplementedThemeTypes({
|
||||||
const latestJarFilePath = fs
|
projectDirPath: buildContext.projectDirPath
|
||||||
.readdirSync(buildContext.keycloakifyBuildDirPath)
|
}).implementedThemeTypes.account;
|
||||||
.filter(fileBasename => fileBasename.endsWith(".jar"))
|
|
||||||
.map(fileBasename =>
|
|
||||||
pathJoin(buildContext.keycloakifyBuildDirPath, fileBasename)
|
|
||||||
)
|
|
||||||
.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs)[0];
|
|
||||||
|
|
||||||
assert(latestJarFilePath !== undefined);
|
|
||||||
|
|
||||||
const metaInfKeycloakThemes = await readMetaInfKeycloakThemes_fromJar({
|
|
||||||
jarFilePath: latestJarFilePath
|
|
||||||
});
|
|
||||||
|
|
||||||
const mainThemeEntry = metaInfKeycloakThemes.themes.find(
|
|
||||||
({ name }) => name === buildContext.themeNames[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
assert(mainThemeEntry !== undefined);
|
|
||||||
|
|
||||||
const doesImplementAccountTheme = mainThemeEntry.types.includes("account");
|
|
||||||
|
|
||||||
return { doesImplementAccountTheme };
|
|
||||||
})();
|
|
||||||
|
|
||||||
const { keycloakVersion, keycloakMajorNumber: keycloakMajorVersionNumber } =
|
const { keycloakVersion, keycloakMajorNumber: keycloakMajorVersionNumber } =
|
||||||
await (async function getKeycloakMajor(): Promise<{
|
await (async () => {
|
||||||
keycloakVersion: string;
|
|
||||||
keycloakMajorNumber: number;
|
|
||||||
}> {
|
|
||||||
if (cliCommandOptions.keycloakVersion !== undefined) {
|
if (cliCommandOptions.keycloakVersion !== undefined) {
|
||||||
return {
|
return {
|
||||||
keycloakVersion: cliCommandOptions.keycloakVersion,
|
keycloakVersion: cliCommandOptions.keycloakVersion,
|
||||||
@ -173,16 +148,6 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|||||||
|
|
||||||
const keycloakMajorNumber = SemVer.parse(keycloakVersion).major;
|
const keycloakMajorNumber = SemVer.parse(keycloakVersion).major;
|
||||||
|
|
||||||
if (doesImplementAccountTheme && keycloakMajorNumber === 22) {
|
|
||||||
console.log(
|
|
||||||
[
|
|
||||||
"Unfortunately, Keycloakify themes that implements an account theme do not work on Keycloak 22",
|
|
||||||
"Please select any other Keycloak version"
|
|
||||||
].join(" ")
|
|
||||||
);
|
|
||||||
return getKeycloakMajor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return { keycloakVersion, keycloakMajorNumber };
|
return { keycloakVersion, keycloakMajorNumber };
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user