2021-02-28 18:40:57 +01:00
|
|
|
import { transformCodebase } from "../tools/transformCodebase";
|
2021-02-21 18:55:06 +01:00
|
|
|
import * as fs from "fs";
|
2022-01-20 01:34:26 +01:00
|
|
|
import { join as pathJoin, basename as pathBasename } from "path";
|
2022-08-16 14:41:06 +07:00
|
|
|
import { replaceImportsFromStaticInJsCode } from "./replacers/replaceImportsFromStaticInJsCode";
|
|
|
|
import { replaceImportsInCssCode } from "./replacers/replaceImportsInCssCode";
|
2021-03-26 15:29:17 +01:00
|
|
|
import { generateFtlFilesCodeFactory, pageIds } from "./generateFtl";
|
2021-10-07 21:00:53 +02:00
|
|
|
import { downloadBuiltinKeycloakTheme } from "../download-builtin-keycloak-theme";
|
2021-03-02 01:05:15 +01:00
|
|
|
import * as child_process from "child_process";
|
2022-07-30 00:51:11 +02:00
|
|
|
import { mockTestingResourcesCommonPath, mockTestingResourcesPath, mockTestingSubDirOfPublicDirBasename } from "../mockTestingResourcesPath";
|
2021-03-22 20:54:28 +01:00
|
|
|
import { isInside } from "../tools/isInside";
|
2022-08-16 14:41:06 +07:00
|
|
|
import type { BuildOptions } from "./BuildOptions";
|
|
|
|
import { assert } from "tsafe/assert";
|
|
|
|
import { Reflect } from "tsafe/Reflect";
|
|
|
|
|
|
|
|
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
|
|
|
|
|
|
|
export namespace BuildOptionsLike {
|
|
|
|
export type Common = {
|
|
|
|
themeName: string;
|
|
|
|
extraPages?: string[];
|
|
|
|
extraThemeProperties?: string[];
|
|
|
|
};
|
|
|
|
|
|
|
|
export type Standalone = Common & {
|
|
|
|
isStandalone: true;
|
|
|
|
urlPathname: string | undefined;
|
|
|
|
};
|
|
|
|
|
|
|
|
export type ExternalAssets = ExternalAssets.SameDomain | ExternalAssets.DifferentDomains;
|
|
|
|
|
|
|
|
export namespace ExternalAssets {
|
|
|
|
export type CommonExternalAssets = Common & {
|
|
|
|
isStandalone: false;
|
|
|
|
};
|
|
|
|
|
|
|
|
export type SameDomain = CommonExternalAssets & {
|
|
|
|
isAppAndKeycloakServerSharingSameDomain: true;
|
|
|
|
};
|
|
|
|
|
|
|
|
export type DifferentDomains = CommonExternalAssets & {
|
|
|
|
isAppAndKeycloakServerSharingSameDomain: false;
|
|
|
|
urlOrigin: string;
|
|
|
|
urlPathname: string | undefined;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
const buildOptions = Reflect<BuildOptions>();
|
|
|
|
|
|
|
|
assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
|
|
|
|
}
|
2021-03-22 20:54:28 +01:00
|
|
|
|
2021-10-11 21:35:40 +02:00
|
|
|
export function generateKeycloakThemeResources(params: {
|
|
|
|
reactAppBuildDirPath: string;
|
|
|
|
keycloakThemeBuildingDirPath: string;
|
2022-04-20 00:39:40 +02:00
|
|
|
keycloakThemeEmailDirPath: string;
|
2022-04-09 20:17:20 +02:00
|
|
|
keycloakVersion: string;
|
2022-08-16 14:41:06 +07:00
|
|
|
buildOptions: BuildOptionsLike;
|
|
|
|
}): { doBundlesEmailTemplate: boolean } {
|
|
|
|
const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, keycloakThemeEmailDirPath, keycloakVersion, buildOptions } = params;
|
|
|
|
|
|
|
|
const themeDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, "login");
|
2021-02-21 18:55:06 +01:00
|
|
|
|
|
|
|
let allCssGlobalsToDefine: Record<string, string> = {};
|
|
|
|
|
|
|
|
transformCodebase({
|
2022-08-16 14:41:06 +07:00
|
|
|
"destDirPath": buildOptions.isStandalone ? pathJoin(themeDirPath, "resources", "build") : reactAppBuildDirPath,
|
2021-02-21 18:55:06 +01:00
|
|
|
"srcDirPath": reactAppBuildDirPath,
|
2021-03-03 02:31:02 +01:00
|
|
|
"transformSourceCode": ({ filePath, sourceCode }) => {
|
2021-03-19 22:39:32 +01:00
|
|
|
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
|
|
|
if (
|
2022-08-16 14:41:06 +07:00
|
|
|
buildOptions.isStandalone &&
|
2021-03-19 22:39:32 +01:00
|
|
|
isInside({
|
2022-07-30 00:51:11 +02:00
|
|
|
"dirPath": pathJoin(reactAppBuildDirPath, mockTestingSubDirOfPublicDirBasename),
|
2021-10-11 21:35:40 +02:00
|
|
|
filePath,
|
2021-03-19 22:39:32 +01:00
|
|
|
})
|
|
|
|
) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
if (/\.css?$/i.test(filePath)) {
|
|
|
|
if (!buildOptions.isStandalone) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2021-10-12 00:26:29 +02:00
|
|
|
const { cssGlobalsToDefine, fixedCssCode } = replaceImportsInCssCode({
|
|
|
|
"cssCode": sourceCode.toString("utf8"),
|
|
|
|
});
|
2021-02-21 18:55:06 +01:00
|
|
|
|
2021-03-28 14:14:43 +02:00
|
|
|
allCssGlobalsToDefine = {
|
|
|
|
...allCssGlobalsToDefine,
|
2021-10-11 21:35:40 +02:00
|
|
|
...cssGlobalsToDefine,
|
2021-03-28 14:14:43 +02:00
|
|
|
};
|
2021-02-21 18:55:06 +01:00
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
return { "modifiedSourceCode": Buffer.from(fixedCssCode, "utf8") };
|
2021-03-28 13:37:02 +02:00
|
|
|
}
|
2021-02-21 18:55:06 +01:00
|
|
|
|
2021-03-28 13:37:02 +02:00
|
|
|
if (/\.js?$/i.test(filePath)) {
|
2022-08-16 14:41:06 +07:00
|
|
|
if (!buildOptions.isStandalone && buildOptions.isAppAndKeycloakServerSharingSameDomain) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2021-03-28 13:37:02 +02:00
|
|
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
|
|
|
"jsCode": sourceCode.toString("utf8"),
|
2022-08-16 14:41:06 +07:00
|
|
|
buildOptions,
|
2021-03-28 13:37:02 +02:00
|
|
|
});
|
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") };
|
2021-02-21 18:55:06 +01:00
|
|
|
}
|
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
return buildOptions.isStandalone ? { "modifiedSourceCode": sourceCode } : undefined;
|
2021-10-11 21:35:40 +02:00
|
|
|
},
|
2021-02-21 18:55:06 +01:00
|
|
|
});
|
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
let doBundlesEmailTemplate: boolean;
|
2022-04-20 00:39:40 +02:00
|
|
|
|
|
|
|
email: {
|
|
|
|
if (!fs.existsSync(keycloakThemeEmailDirPath)) {
|
|
|
|
console.log(
|
|
|
|
[
|
|
|
|
`Not bundling email template because ${pathBasename(keycloakThemeEmailDirPath)} does not exist`,
|
2022-04-28 09:46:49 +02:00
|
|
|
`To start customizing the email template, run: 👉 npx create-keycloak-email-directory 👈`,
|
2022-04-20 00:39:40 +02:00
|
|
|
].join("\n"),
|
|
|
|
);
|
2022-08-16 14:41:06 +07:00
|
|
|
doBundlesEmailTemplate = false;
|
2022-04-20 00:39:40 +02:00
|
|
|
break email;
|
|
|
|
}
|
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
doBundlesEmailTemplate = true;
|
2022-04-20 00:39:40 +02:00
|
|
|
|
|
|
|
transformCodebase({
|
|
|
|
"srcDirPath": keycloakThemeEmailDirPath,
|
|
|
|
"destDirPath": pathJoin(themeDirPath, "..", "email"),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-02-21 18:55:06 +01:00
|
|
|
const { generateFtlFilesCode } = generateFtlFilesCodeFactory({
|
2021-10-12 00:26:29 +02:00
|
|
|
"indexHtmlCode": fs.readFileSync(pathJoin(reactAppBuildDirPath, "index.html")).toString("utf8"),
|
2022-08-16 14:41:06 +07:00
|
|
|
"cssGlobalsToDefine": allCssGlobalsToDefine,
|
|
|
|
"buildOptions": buildOptions,
|
2021-02-21 18:55:06 +01:00
|
|
|
});
|
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
[...pageIds, ...(buildOptions.extraPages ?? [])].forEach(pageId => {
|
2021-03-06 22:41:36 +01:00
|
|
|
const { ftlCode } = generateFtlFilesCode({ pageId });
|
2021-02-21 18:55:06 +01:00
|
|
|
|
2021-04-11 18:18:52 +02:00
|
|
|
fs.mkdirSync(themeDirPath, { "recursive": true });
|
|
|
|
|
2021-10-12 00:26:29 +02:00
|
|
|
fs.writeFileSync(pathJoin(themeDirPath, pageId), Buffer.from(ftlCode, "utf8"));
|
2021-02-21 18:55:06 +01:00
|
|
|
});
|
|
|
|
|
2021-03-02 01:05:15 +01:00
|
|
|
{
|
2021-03-03 02:31:02 +01:00
|
|
|
const tmpDirPath = pathJoin(themeDirPath, "..", "tmp_xxKdLpdIdLd");
|
2021-03-02 01:05:15 +01:00
|
|
|
|
2021-10-06 17:22:52 +02:00
|
|
|
downloadBuiltinKeycloakTheme({
|
|
|
|
keycloakVersion,
|
2021-10-11 21:35:40 +02:00
|
|
|
"destDirPath": tmpDirPath,
|
2021-03-02 01:05:15 +01:00
|
|
|
});
|
|
|
|
|
2021-03-19 22:39:32 +01:00
|
|
|
const themeResourcesDirPath = pathJoin(themeDirPath, "resources");
|
2021-03-08 00:09:52 +01:00
|
|
|
|
2021-03-03 02:31:02 +01:00
|
|
|
transformCodebase({
|
2021-10-12 00:26:29 +02:00
|
|
|
"srcDirPath": pathJoin(tmpDirPath, "keycloak", "login", "resources"),
|
2021-10-11 21:35:40 +02:00
|
|
|
"destDirPath": themeResourcesDirPath,
|
2021-03-08 00:09:52 +01:00
|
|
|
});
|
|
|
|
|
2021-10-12 00:26:29 +02:00
|
|
|
const reactAppPublicDirPath = pathJoin(reactAppBuildDirPath, "..", "public");
|
2021-03-08 00:09:52 +01:00
|
|
|
|
|
|
|
transformCodebase({
|
2022-01-20 01:34:26 +01:00
|
|
|
"srcDirPath": pathJoin(tmpDirPath, "keycloak", "common", "resources"),
|
2022-07-30 00:51:11 +02:00
|
|
|
"destDirPath": pathJoin(themeResourcesDirPath, pathBasename(mockTestingResourcesCommonPath)),
|
2021-03-08 00:09:52 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
transformCodebase({
|
2022-01-20 01:34:26 +01:00
|
|
|
"srcDirPath": themeResourcesDirPath,
|
2022-07-30 00:51:11 +02:00
|
|
|
"destDirPath": pathJoin(reactAppPublicDirPath, mockTestingResourcesPath),
|
2021-03-03 02:31:02 +01:00
|
|
|
});
|
2021-03-02 01:05:15 +01:00
|
|
|
|
2022-07-30 00:51:11 +02:00
|
|
|
const keycloakResourcesWithinPublicDirPath = pathJoin(reactAppPublicDirPath, mockTestingSubDirOfPublicDirBasename);
|
2021-03-08 00:09:52 +01:00
|
|
|
|
|
|
|
fs.writeFileSync(
|
|
|
|
pathJoin(keycloakResourcesWithinPublicDirPath, "README.txt"),
|
2022-01-20 01:34:26 +01:00
|
|
|
Buffer.from(
|
|
|
|
["This is just a test folder that helps develop", "the login and register page without having to run a Keycloak container"].join(" "),
|
|
|
|
),
|
2021-03-08 00:09:52 +01:00
|
|
|
);
|
|
|
|
|
2021-10-12 00:26:29 +02:00
|
|
|
fs.writeFileSync(pathJoin(keycloakResourcesWithinPublicDirPath, ".gitignore"), Buffer.from("*", "utf8"));
|
2021-03-10 22:45:09 +01:00
|
|
|
|
2021-03-03 02:31:02 +01:00
|
|
|
child_process.execSync(`rm -r ${tmpDirPath}`);
|
2021-03-02 01:05:15 +01:00
|
|
|
}
|
|
|
|
|
2021-02-22 00:35:52 +01:00
|
|
|
fs.writeFileSync(
|
|
|
|
pathJoin(themeDirPath, "theme.properties"),
|
2022-08-16 14:41:06 +07:00
|
|
|
Buffer.from(["parent=keycloak", ...(buildOptions.extraThemeProperties ?? [])].join("\n\n"), "utf8"),
|
2021-02-22 00:35:52 +01:00
|
|
|
);
|
2022-04-20 00:39:40 +02:00
|
|
|
|
2022-08-16 14:41:06 +07:00
|
|
|
return { doBundlesEmailTemplate };
|
2021-02-21 18:55:06 +01:00
|
|
|
}
|