From de390678fda5b406168863c9637b1649e98e3b25 Mon Sep 17 00:00:00 2001 From: garronej Date: Wed, 21 Jun 2023 03:54:43 +0200 Subject: [PATCH] Deprecate the extraPages options, analyze the code to detect extra pages --- keycloakify-json-schema.json | 12 ------ src/bin/getSrcDirPath.ts | 2 +- src/bin/keycloakify/BuildOptions.ts | 16 +------- .../generateTheme/generateTheme.ts | 17 ++++---- .../generateTheme/readExtraPageNames.ts | 38 +++++++++++++++++ .../generateTheme/readFieldNameUsage.ts | 4 +- src/bin/keycloakify/parsedPackageJson.ts | 7 ---- src/bin/tools/crawl.ts | 41 +++++++++++-------- src/bin/tools/transformCodebase.ts | 4 +- 9 files changed, 73 insertions(+), 68 deletions(-) create mode 100644 src/bin/keycloakify/generateTheme/readExtraPageNames.ts diff --git a/keycloakify-json-schema.json b/keycloakify-json-schema.json index 2606f486..254b2e50 100644 --- a/keycloakify-json-schema.json +++ b/keycloakify-json-schema.json @@ -30,18 +30,6 @@ "type": "string" } }, - "extraLoginPages": { - "type": "array", - "items": { - "type": "string" - } - }, - "extraAccountPages": { - "type": "array", - "items": { - "type": "string" - } - }, "extraThemeProperties": { "type": "array", "items": { diff --git a/src/bin/getSrcDirPath.ts b/src/bin/getSrcDirPath.ts index 648a479f..15a4cbd2 100644 --- a/src/bin/getSrcDirPath.ts +++ b/src/bin/getSrcDirPath.ts @@ -10,7 +10,7 @@ export function getThemeSrcDirPath(params: { projectDirPath: string }) { const srcDirPath = pathJoin(projectDirPath, "src"); - const themeSrcDirPath: string | undefined = crawl(srcDirPath) + const themeSrcDirPath: string | undefined = crawl({ "dirPath": srcDirPath, "returnedPathsType": "relative to dirPath" }) .map(fileRelativePath => { const split = fileRelativePath.split(themeSrcDirBasename); diff --git a/src/bin/keycloakify/BuildOptions.ts b/src/bin/keycloakify/BuildOptions.ts index 0858f973..b32f9501 100644 --- a/src/bin/keycloakify/BuildOptions.ts +++ b/src/bin/keycloakify/BuildOptions.ts @@ -17,8 +17,6 @@ export namespace BuildOptions { themeVersion: string; themeName: string; extraThemeNames: string[]; - extraLoginPages: string[] | undefined; - extraAccountPages: string[] | undefined; extraThemeProperties: string[] | undefined; groupId: string; artifactId: string; @@ -108,17 +106,7 @@ export function readBuildOptions(params: { projectDirPath: string; processArgv: const common: BuildOptions.Common = (() => { const { name, keycloakify = {}, version, homepage } = parsedPackageJson; - const { - extraPages, - extraLoginPages, - extraAccountPages, - extraThemeProperties, - groupId, - artifactId, - bundler, - keycloakVersionDefaultAssets, - extraThemeNames = [] - } = keycloakify ?? {}; + const { extraThemeProperties, groupId, artifactId, bundler, keycloakVersionDefaultAssets, extraThemeNames = [] } = keycloakify ?? {}; const themeName = keycloakify.themeName ?? @@ -160,8 +148,6 @@ export function readBuildOptions(params: { projectDirPath: string; processArgv: ); })(), "themeVersion": process.env.KEYCLOAKIFY_THEME_VERSION ?? process.env.KEYCLOAKIFY_VERSION ?? version ?? "0.0.0", - "extraLoginPages": [...(extraPages ?? []), ...(extraLoginPages ?? [])], - extraAccountPages, extraThemeProperties, "isSilent": isSilentCliParamProvided, "keycloakVersionDefaultAssets": keycloakVersionDefaultAssets ?? "11.0.3", diff --git a/src/bin/keycloakify/generateTheme/generateTheme.ts b/src/bin/keycloakify/generateTheme/generateTheme.ts index 9e6df82c..adebfa77 100644 --- a/src/bin/keycloakify/generateTheme/generateTheme.ts +++ b/src/bin/keycloakify/generateTheme/generateTheme.ts @@ -10,14 +10,13 @@ import type { BuildOptions } from "../BuildOptions"; import { assert } from "tsafe/assert"; import { downloadKeycloakStaticResources } from "./downloadKeycloakStaticResources"; import { readFieldNameUsage } from "./readFieldNameUsage"; +import { readExtraPagesNames } from "./readExtraPageNames"; export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets; export namespace BuildOptionsLike { export type Common = { themeName: string; - extraLoginPages: string[] | undefined; - extraAccountPages: string[] | undefined; extraThemeProperties: string[] | undefined; isSilent: boolean; themeVersion: string; @@ -163,14 +162,12 @@ export async function generateTheme(params: { return accountThemePageIds; } })(), - ...((() => { - switch (themeType) { - case "login": - return buildOptions.extraLoginPages; - case "account": - return buildOptions.extraAccountPages; - } - })() ?? []) + ...(themeSrcDirPath === undefined + ? [] + : readExtraPagesNames({ + themeType, + themeSrcDirPath + })) ].forEach(pageId => { const { ftlCode } = generateFtlFilesCode({ pageId }); diff --git a/src/bin/keycloakify/generateTheme/readExtraPageNames.ts b/src/bin/keycloakify/generateTheme/readExtraPageNames.ts new file mode 100644 index 00000000..3c21f399 --- /dev/null +++ b/src/bin/keycloakify/generateTheme/readExtraPageNames.ts @@ -0,0 +1,38 @@ +import { crawl } from "../../tools/crawl"; +import { type ThemeType, accountThemePageIds, loginThemePageIds } from "../generateFtl"; +import { id } from "tsafe/id"; +import { removeDuplicates } from "evt/tools/reducers/removeDuplicates"; +import * as fs from "fs"; +import { join as pathJoin } from "path"; + +export function readExtraPagesNames(params: { themeSrcDirPath: string; themeType: ThemeType }): string[] { + const { themeSrcDirPath, themeType } = params; + + const filePaths = crawl({ + "dirPath": pathJoin(themeSrcDirPath, themeType), + "returnedPathsType": "absolute" + }).filter(filePath => /\.(ts|tsx|js|jsx)$/.test(filePath)); + + const candidateFilePaths = filePaths.filter(filePath => /kcContext\.[^.]+$/.test(filePath)); + + if (candidateFilePaths.length === 0) { + candidateFilePaths.push(...filePaths); + } + + const extraPages: string[] = []; + + for (const candidateFilPath of candidateFilePaths) { + const rawSourceFile = fs.readFileSync(candidateFilPath).toString("utf8"); + + extraPages.push(...Array.from(rawSourceFile.matchAll(/["']?pageId["']?\s*:\s*["']([^.]+.ftl)["']/g), m => m[1])); + } + + return extraPages.reduce(...removeDuplicates()).filter(pageId => { + switch (themeType) { + case "account": + return !id(accountThemePageIds).includes(pageId); + case "login": + return !id(loginThemePageIds).includes(pageId); + } + }); +} diff --git a/src/bin/keycloakify/generateTheme/readFieldNameUsage.ts b/src/bin/keycloakify/generateTheme/readFieldNameUsage.ts index 4bcaf3fd..9a930a2e 100644 --- a/src/bin/keycloakify/generateTheme/readFieldNameUsage.ts +++ b/src/bin/keycloakify/generateTheme/readFieldNameUsage.ts @@ -73,9 +73,7 @@ export function readFieldNameUsage(params: { })() ] as const ).filter(exclude(undefined))) { - const filePaths = crawl(srcDirPath) - .filter(filePath => /\.(ts|tsx|js|jsx)$/.test(filePath)) - .map(filePath => pathJoin(srcDirPath, filePath)); + const filePaths = crawl({ "dirPath": srcDirPath, "returnedPathsType": "absolute" }).filter(filePath => /\.(ts|tsx|js|jsx)$/.test(filePath)); for (const filePath of filePaths) { const rawSourceFile = fs.readFileSync(filePath).toString("utf8"); diff --git a/src/bin/keycloakify/parsedPackageJson.ts b/src/bin/keycloakify/parsedPackageJson.ts index 889c4650..972cc960 100644 --- a/src/bin/keycloakify/parsedPackageJson.ts +++ b/src/bin/keycloakify/parsedPackageJson.ts @@ -11,10 +11,6 @@ export type ParsedPackageJson = { version?: string; homepage?: string; keycloakify?: { - /** @deprecated: use extraLoginPages instead */ - extraPages?: string[]; - extraLoginPages?: string[]; - extraAccountPages?: string[]; extraThemeProperties?: string[]; areAppAndKeycloakServerSharingSameDomain?: boolean; artifactId?: string; @@ -34,9 +30,6 @@ export const zParsedPackageJson = z.object({ "homepage": z.string().optional(), "keycloakify": z .object({ - "extraPages": z.array(z.string()).optional(), - "extraLoginPages": z.array(z.string()).optional(), - "extraAccountPages": z.array(z.string()).optional(), "extraThemeProperties": z.array(z.string()).optional(), "areAppAndKeycloakServerSharingSameDomain": z.boolean().optional(), "artifactId": z.string().optional(), diff --git a/src/bin/tools/crawl.ts b/src/bin/tools/crawl.ts index 4882c5e6..dd53a6d9 100644 --- a/src/bin/tools/crawl.ts +++ b/src/bin/tools/crawl.ts @@ -1,27 +1,32 @@ import * as fs from "fs"; import * as path from "path"; -/** List all files in a given directory return paths relative to the dir_path */ -export const crawl = (() => { - const crawlRec = (dir_path: string, paths: string[]) => { - for (const file_name of fs.readdirSync(dir_path)) { - const file_path = path.join(dir_path, file_name); +const crawlRec = (dir_path: string, paths: string[]) => { + for (const file_name of fs.readdirSync(dir_path)) { + const file_path = path.join(dir_path, file_name); - if (fs.lstatSync(file_path).isDirectory()) { - crawlRec(file_path, paths); + if (fs.lstatSync(file_path).isDirectory()) { + crawlRec(file_path, paths); - continue; - } - - paths.push(file_path); + continue; } - }; - return function crawl(dir_path: string): string[] { - const paths: string[] = []; + paths.push(file_path); + } +}; - crawlRec(dir_path, paths); +/** List all files in a given directory return paths relative to the dir_path */ +export function crawl(params: { dirPath: string; returnedPathsType: "absolute" | "relative to dirPath" }): string[] { + const { dirPath, returnedPathsType } = params; - return paths.map(file_path => path.relative(dir_path, file_path)); - }; -})(); + const filePaths: string[] = []; + + crawlRec(dirPath, filePaths); + + switch (returnedPathsType) { + case "absolute": + return filePaths; + case "relative to dirPath": + return filePaths.map(filePath => path.relative(dirPath, filePath)); + } +} diff --git a/src/bin/tools/transformCodebase.ts b/src/bin/tools/transformCodebase.ts index 03c75cae..9e04074a 100644 --- a/src/bin/tools/transformCodebase.ts +++ b/src/bin/tools/transformCodebase.ts @@ -20,12 +20,12 @@ export function transformCodebase(params: { srcDirPath: string; destDirPath: str })) } = params; - for (const file_relative_path of crawl(srcDirPath)) { + for (const file_relative_path of crawl({ "dirPath": srcDirPath, "returnedPathsType": "relative to dirPath" })) { const filePath = path.join(srcDirPath, file_relative_path); const transformSourceCodeResult = transformSourceCode({ "sourceCode": fs.readFileSync(filePath), - "filePath": path.join(srcDirPath, file_relative_path) + filePath }); if (transformSourceCodeResult === undefined) {