diff --git a/.gitignore b/.gitignore index 0cfc38c5..03ef1335 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ jspm_packages .devcontainer /stories/assets/fonts/ +/.storybook/static/keycloak_static/ diff --git a/package.json b/package.json index 6c6c5f47..9e919ba3 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "prepare": "yarn generate-i18n-messages && yarn copy-fonts", + "prepare": "yarn generate-i18n-messages && yarn copy-fonts && yarn setup-keycloak-static-assets-for-storybook", "build": "rimraf dist/ && tsc -p src/bin && tsc -p src/tsconfig.json && tsc-alias -p src/tsconfig.json && yarn grant-exec-perms && yarn copy-files dist/", "build:watch": "tsc -p src/tsconfig.json && (concurrently \"tsc -p src/tsconfig.json -w\" \"tsc-alias -p src/tsconfig.json\")", "generate:json-schema": "ts-node scripts/generate-json-schema.ts", @@ -27,7 +27,8 @@ "tsc-watch": "tsc -p src/bin -w & tsc -p src/lib -w", "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook", - "copy-fonts": "copyfiles -u 2 .storybook/static/fonts/**/* stories/assets" + "copy-fonts": "copyfiles -u 2 .storybook/static/fonts/**/* stories/assets", + "setup-keycloak-static-assets-for-storybook": "ts-node --skipProject scripts/setup-keycloak-static-assets-for-storybook.ts" }, "bin": { "keycloakify": "dist/bin/keycloakify/index.js", diff --git a/scripts/setup-keycloak-static-assets-for-storybook.ts b/scripts/setup-keycloak-static-assets-for-storybook.ts new file mode 100644 index 00000000..c8af853a --- /dev/null +++ b/scripts/setup-keycloak-static-assets-for-storybook.ts @@ -0,0 +1,16 @@ +import { downloadKeycloakStaticResources } from "../src/bin/keycloakify/generateTheme/downloadKeycloakStaticResources"; +import { getProjectRoot } from "../src/bin/tools/getProjectRoot"; +import { join as pathJoin } from "path"; +import { mockTestingSubDirOfPublicDirBasename } from "../src/bin/mockTestingResourcesPath"; +import { defaultKeycloakVersionDefaultAssets } from "../src/bin/keycloakify/BuildOptions"; + +(async () => { + await downloadKeycloakStaticResources({ + "isSilent": false, + "keycloakVersion": defaultKeycloakVersionDefaultAssets, + "themeType": "login", + "themeDirPath": pathJoin(getProjectRoot(), ".storybook", "static", mockTestingSubDirOfPublicDirBasename) + }); + + console.log("Done"); +})(); diff --git a/src/bin/keycloakify/BuildOptions.ts b/src/bin/keycloakify/BuildOptions.ts index 30831022..6ad833b4 100644 --- a/src/bin/keycloakify/BuildOptions.ts +++ b/src/bin/keycloakify/BuildOptions.ts @@ -53,6 +53,8 @@ export namespace BuildOptions { } } +export const defaultKeycloakVersionDefaultAssets = "11.0.3"; + export function readBuildOptions(params: { projectDirPath: string; isExternalAssetsCliParamProvided: boolean; isSilent: boolean }): BuildOptions { const { projectDirPath, isExternalAssetsCliParamProvided, isSilent } = params; @@ -144,7 +146,7 @@ export function readBuildOptions(params: { projectDirPath: string; isExternalAss extraAccountPages, extraThemeProperties, isSilent, - "keycloakVersionDefaultAssets": keycloakVersionDefaultAssets ?? "11.0.3", + "keycloakVersionDefaultAssets": keycloakVersionDefaultAssets ?? defaultKeycloakVersionDefaultAssets, "reactAppBuildDirPath": (() => { let { reactAppBuildDirPath = undefined } = parsedPackageJson.keycloakify ?? {}; diff --git a/src/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.ts b/src/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.ts new file mode 100644 index 00000000..111f5654 --- /dev/null +++ b/src/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.ts @@ -0,0 +1,38 @@ +import { transformCodebase } from "../../tools/transformCodebase"; +import * as fs from "fs"; +import { join as pathJoin, relative as pathRelative } from "path"; +import type { ThemeType } from "../generateFtl"; +import { downloadBuiltinKeycloakTheme } from "../../download-builtin-keycloak-theme"; +import { mockTestingResourcesCommonPath, mockTestingResourcesPath, mockTestingSubDirOfPublicDirBasename } from "../../mockTestingResourcesPath"; + +export async function downloadKeycloakStaticResources( + // prettier-ignore + params: { + themeType: ThemeType; + themeDirPath: string; + isSilent: boolean; + keycloakVersion: string; + } +) { + const { themeType, isSilent, themeDirPath, keycloakVersion } = params; + + const tmpDirPath = pathJoin(themeDirPath, "..", "tmp_suLeKsxId"); + + await downloadBuiltinKeycloakTheme({ + keycloakVersion, + "destDirPath": tmpDirPath, + isSilent + }); + + transformCodebase({ + "srcDirPath": pathJoin(tmpDirPath, "keycloak", themeType, "resources"), + "destDirPath": pathJoin(themeDirPath, pathRelative(mockTestingSubDirOfPublicDirBasename, mockTestingResourcesPath)) + }); + + transformCodebase({ + "srcDirPath": pathJoin(tmpDirPath, "keycloak", "common", "resources"), + "destDirPath": pathJoin(themeDirPath, pathRelative(mockTestingSubDirOfPublicDirBasename, mockTestingResourcesCommonPath)) + }); + + fs.rmSync(tmpDirPath, { "recursive": true, "force": true }); +} diff --git a/src/bin/keycloakify/generateKeycloakThemeResources.ts b/src/bin/keycloakify/generateTheme/generateTheme.ts similarity index 76% rename from src/bin/keycloakify/generateKeycloakThemeResources.ts rename to src/bin/keycloakify/generateTheme/generateTheme.ts index 3dec85bb..a2bd9f64 100644 --- a/src/bin/keycloakify/generateKeycloakThemeResources.ts +++ b/src/bin/keycloakify/generateTheme/generateTheme.ts @@ -1,14 +1,14 @@ -import { transformCodebase } from "../tools/transformCodebase"; +import { transformCodebase } from "../../tools/transformCodebase"; import * as fs from "fs"; -import { join as pathJoin, basename as pathBasename } from "path"; -import { replaceImportsFromStaticInJsCode } from "./replacers/replaceImportsFromStaticInJsCode"; -import { replaceImportsInCssCode } from "./replacers/replaceImportsInCssCode"; -import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds, themeTypes, type ThemeType } from "./generateFtl"; -import { downloadBuiltinKeycloakTheme } from "../download-builtin-keycloak-theme"; -import { mockTestingResourcesCommonPath, mockTestingResourcesPath, mockTestingSubDirOfPublicDirBasename } from "../mockTestingResourcesPath"; -import { isInside } from "../tools/isInside"; -import type { BuildOptions } from "./BuildOptions"; +import { join as pathJoin } from "path"; +import { replaceImportsFromStaticInJsCode } from "../replacers/replaceImportsFromStaticInJsCode"; +import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode"; +import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds, themeTypes, type ThemeType } from "../generateFtl"; +import { mockTestingSubDirOfPublicDirBasename } from "../../mockTestingResourcesPath"; +import { isInside } from "../../tools/isInside"; +import type { BuildOptions } from "../BuildOptions"; import { assert } from "tsafe/assert"; +import { downloadKeycloakStaticResources } from "./downloadKeycloakStaticResources"; export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets; @@ -21,6 +21,7 @@ export namespace BuildOptionsLike { isSilent: boolean; customUserAttributes: string[]; themeVersion: string; + keycloakVersionDefaultAssets: string; }; export type Standalone = Common & { @@ -49,15 +50,14 @@ export namespace BuildOptionsLike { assert(); -export async function generateKeycloakThemeResources(params: { +export async function generateTheme(params: { reactAppBuildDirPath: string; keycloakThemeBuildingDirPath: string; emailThemeSrcDirPath: string | undefined; - keycloakVersion: string; buildOptions: BuildOptionsLike; keycloakifyVersion: string; }): Promise<{ doBundlesEmailTemplate: boolean }> { - const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, keycloakVersion, buildOptions, keycloakifyVersion } = params; + const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, buildOptions, keycloakifyVersion } = params; const getThemeDirPath = (themeType: ThemeType | "email") => pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, themeType); @@ -172,47 +172,33 @@ export async function generateKeycloakThemeResources(params: { fs.writeFileSync(pathJoin(themeDirPath, pageId), Buffer.from(ftlCode, "utf8")); }); + const downloadKeycloakStaticResources_configured = async (themeDirPath: string) => + await downloadKeycloakStaticResources({ + "isSilent": buildOptions.isSilent, + "keycloakVersion": buildOptions.keycloakVersionDefaultAssets, + themeDirPath, + themeType + }); + + await downloadKeycloakStaticResources_configured(themeDirPath); + { - const tmpDirPath = pathJoin(themeDirPath, "..", "tmp_xxKdLpdIdLd"); + const keycloakResourcesWithinPublicDirPath = pathJoin(reactAppBuildDirPath, "..", "public", mockTestingSubDirOfPublicDirBasename); - await downloadBuiltinKeycloakTheme({ - keycloakVersion, - "destDirPath": tmpDirPath, - isSilent: buildOptions.isSilent - }); - - const themeResourcesDirPath = pathJoin(themeDirPath, "resources"); - - transformCodebase({ - "srcDirPath": pathJoin(tmpDirPath, "keycloak", themeType, "resources"), - "destDirPath": themeResourcesDirPath - }); - - const reactAppPublicDirPath = pathJoin(reactAppBuildDirPath, "..", "public"); - - transformCodebase({ - "srcDirPath": pathJoin(tmpDirPath, "keycloak", "common", "resources"), - "destDirPath": pathJoin(themeResourcesDirPath, pathBasename(mockTestingResourcesCommonPath)) - }); - - transformCodebase({ - "srcDirPath": themeResourcesDirPath, - "destDirPath": pathJoin(reactAppPublicDirPath, mockTestingResourcesPath) - }); - - const keycloakResourcesWithinPublicDirPath = pathJoin(reactAppPublicDirPath, mockTestingSubDirOfPublicDirBasename); + await downloadKeycloakStaticResources_configured(keycloakResourcesWithinPublicDirPath); fs.writeFileSync( pathJoin(keycloakResourcesWithinPublicDirPath, "README.txt"), Buffer.from( - ["This is just a test folder that helps develop", "the login and register page without having to run a Keycloak container"].join( - " " - ) + // prettier-ignore + [ + "This is just a test folder that helps develop", + "the login and register page without having to run a Keycloak container" + ].join(" ") ) ); fs.writeFileSync(pathJoin(keycloakResourcesWithinPublicDirPath, ".gitignore"), Buffer.from("*", "utf8")); - fs.rmSync(tmpDirPath, { recursive: true, force: true }); } fs.writeFileSync( diff --git a/src/bin/keycloakify/generateTheme/index.ts b/src/bin/keycloakify/generateTheme/index.ts new file mode 100644 index 00000000..e31458d9 --- /dev/null +++ b/src/bin/keycloakify/generateTheme/index.ts @@ -0,0 +1 @@ +export * from "./generateTheme"; diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index 2640de18..28146b98 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -1,4 +1,4 @@ -import { generateKeycloakThemeResources } from "./generateKeycloakThemeResources"; +import { generateTheme } from "./generateTheme"; import { generateJavaStackFiles } from "./generateJavaStackFiles"; import { join as pathJoin, relative as pathRelative, basename as pathBasename, sep as pathSep } from "path"; import * as child_process from "child_process"; @@ -26,7 +26,7 @@ export async function main() { "isSilent": isSilent }); - const { doBundlesEmailTemplate } = await generateKeycloakThemeResources({ + const { doBundlesEmailTemplate } = await generateTheme({ keycloakThemeBuildingDirPath: buildOptions.keycloakifyBuildDirPath, "emailThemeSrcDirPath": (() => { const { emailThemeSrcDirPath } = getEmailThemeSrcDirPath({ projectDirPath }); @@ -39,7 +39,6 @@ export async function main() { })(), "reactAppBuildDirPath": buildOptions.reactAppBuildDirPath, buildOptions, - "keycloakVersion": buildOptions.keycloakVersionDefaultAssets, "keycloakifyVersion": (() => { const version = JSON.parse(fs.readFileSync(pathJoin(getProjectRoot(), "package.json")).toString("utf8"))["version"];