From db23ab0bc24a4f2e19af69dfbed1a6affb684110 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sat, 20 Jul 2024 22:43:14 +0200 Subject: [PATCH] Introduce build option: accountThemeImplementation --- src/bin/keycloakify/buildJars/buildJar.ts | 4 +- src/bin/keycloakify/buildJars/buildJars.ts | 7 +- .../generateResourcesForMainTheme.ts | 42 +- src/bin/shared/buildContext.ts | 477 ++++++++++-------- src/vite-plugin/vite-plugin.ts | 12 +- 5 files changed, 295 insertions(+), 247 deletions(-) diff --git a/src/bin/keycloakify/buildJars/buildJar.ts b/src/bin/keycloakify/buildJars/buildJar.ts index e1d58213..59a692cc 100644 --- a/src/bin/keycloakify/buildJars/buildJar.ts +++ b/src/bin/keycloakify/buildJars/buildJar.ts @@ -24,7 +24,7 @@ export type BuildContextLike = BuildContextLike_generatePom & { artifactId: string; themeVersion: string; cacheDirPath: string; - recordIsImplementedByThemeType: BuildContext["recordIsImplementedByThemeType"]; + implementedThemeTypes: BuildContext["implementedThemeTypes"]; }; assert(); @@ -135,7 +135,7 @@ export async function buildJar(params: { } route_legacy_pages: { - if (!buildContext.recordIsImplementedByThemeType.login) { + if (!buildContext.implementedThemeTypes.login.isImplemented) { break route_legacy_pages; } diff --git a/src/bin/keycloakify/buildJars/buildJars.ts b/src/bin/keycloakify/buildJars/buildJars.ts index 2a3c891b..1b11a05b 100644 --- a/src/bin/keycloakify/buildJars/buildJars.ts +++ b/src/bin/keycloakify/buildJars/buildJars.ts @@ -10,9 +10,8 @@ import type { BuildContext } from "../../shared/buildContext"; export type BuildContextLike = BuildContextLike_buildJar & { projectDirPath: string; keycloakifyBuildDirPath: string; - recordIsImplementedByThemeType: BuildContext["recordIsImplementedByThemeType"]; + implementedThemeTypes: BuildContext["implementedThemeTypes"]; jarTargets: BuildContext["jarTargets"]; - doUseAccountV3: boolean; }; assert(); @@ -24,8 +23,8 @@ export async function buildJars(params: { const { resourcesDirPath, buildContext } = params; const doesImplementAccountV1Theme = - buildContext.recordIsImplementedByThemeType.account && - !buildContext.doUseAccountV3; + buildContext.implementedThemeTypes.account.isImplemented && + buildContext.implementedThemeTypes.account.type === "Multi-Page"; await Promise.all( keycloakAccountV1Versions diff --git a/src/bin/keycloakify/generateResources/generateResourcesForMainTheme.ts b/src/bin/keycloakify/generateResources/generateResourcesForMainTheme.ts index 00577423..4012c774 100644 --- a/src/bin/keycloakify/generateResources/generateResourcesForMainTheme.ts +++ b/src/bin/keycloakify/generateResources/generateResourcesForMainTheme.ts @@ -53,10 +53,9 @@ export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode & projectDirPath: string; projectBuildDirPath: string; environmentVariables: { name: string; default: string }[]; - recordIsImplementedByThemeType: BuildContext["recordIsImplementedByThemeType"]; + implementedThemeTypes: BuildContext["implementedThemeTypes"]; themeSrcDirPath: string; bundler: { type: "vite" } | { type: "webpack" }; - doUseAccountV3: boolean; }; assert(); @@ -74,11 +73,15 @@ export async function generateResourcesForMainTheme(params: { }; for (const themeType of ["login", "account"] as const) { - const isAccountV3 = themeType === "account" && buildContext.doUseAccountV3; - if (!buildContext.recordIsImplementedByThemeType[themeType]) { + if (!buildContext.implementedThemeTypes[themeType].isImplemented) { continue; } + const isForAccountSpa = + themeType === "account" && + (assert(buildContext.implementedThemeTypes.account.isImplemented), + buildContext.implementedThemeTypes.account.type === "Single-Page"); + const themeTypeDirPath = getThemeTypeDirPath({ themeType }); apply_replacers_and_move_to_theme_resources: { @@ -93,7 +96,7 @@ export async function generateResourcesForMainTheme(params: { if ( themeType === "account" && - buildContext.recordIsImplementedByThemeType.login + buildContext.implementedThemeTypes.login.isImplemented ) { // NOTE: We prevent doing it twice, it has been done for the login theme. @@ -184,10 +187,10 @@ export async function generateResourcesForMainTheme(params: { case "login": return LOGIN_THEME_PAGE_IDS; case "account": - return isAccountV3 ? ["index.ftl"] : ACCOUNT_THEME_PAGE_IDS; + return isForAccountSpa ? ["index.ftl"] : ACCOUNT_THEME_PAGE_IDS; } })(), - ...(isAccountV3 + ...(isForAccountSpa ? [] : readExtraPagesNames({ themeType, @@ -203,7 +206,7 @@ export async function generateResourcesForMainTheme(params: { }); i18n_messages_generation: { - if (isAccountV3) { + if (isForAccountSpa) { break i18n_messages_generation; } @@ -230,7 +233,7 @@ export async function generateResourcesForMainTheme(params: { } keycloak_static_resources: { - if (isAccountV3) { + if (isForAccountSpa) { break keycloak_static_resources; } @@ -256,13 +259,13 @@ export async function generateResourcesForMainTheme(params: { `parent=${(() => { switch (themeType) { case "account": - return isAccountV3 ? "base" : ACCOUNT_V1_THEME_NAME; + return isForAccountSpa ? "base" : ACCOUNT_V1_THEME_NAME; case "login": return "keycloak"; } assert>(false); })()}`, - ...(isAccountV3 ? ["deprecatedMode=false"] : []), + ...(isForAccountSpa ? ["deprecatedMode=false"] : []), ...(buildContext.extraThemeProperties ?? []), ...buildContext.environmentVariables.map( ({ name, default: defaultValue }) => @@ -275,7 +278,7 @@ export async function generateResourcesForMainTheme(params: { } email: { - if (!buildContext.recordIsImplementedByThemeType.email) { + if (!buildContext.implementedThemeTypes.email.isImplemented) { break email; } @@ -288,11 +291,11 @@ export async function generateResourcesForMainTheme(params: { } bring_in_account_v1: { - if (buildContext.doUseAccountV3) { + if (!buildContext.implementedThemeTypes.account.isImplemented) { break bring_in_account_v1; } - if (!buildContext.recordIsImplementedByThemeType.account) { + if (buildContext.implementedThemeTypes.account.type !== "Multi-Page") { break bring_in_account_v1; } @@ -303,7 +306,10 @@ export async function generateResourcesForMainTheme(params: { } bring_in_account_v3_i18n_messages: { - if (!buildContext.doUseAccountV3) { + if (!buildContext.implementedThemeTypes.account.isImplemented) { + break bring_in_account_v3_i18n_messages; + } + if (buildContext.implementedThemeTypes.account.type !== "Single-Page") { break bring_in_account_v3_i18n_messages; } @@ -340,12 +346,12 @@ export async function generateResourcesForMainTheme(params: { metaInfKeycloakThemes.themes.push({ name: themeName, - types: objectEntries(buildContext.recordIsImplementedByThemeType) - .filter(([, isImplemented]) => isImplemented) + types: objectEntries(buildContext.implementedThemeTypes) + .filter(([, { isImplemented }]) => isImplemented) .map(([themeType]) => themeType) }); - if (buildContext.recordIsImplementedByThemeType.account) { + if (buildContext.implementedThemeTypes.account.isImplemented) { metaInfKeycloakThemes.themes.push({ name: ACCOUNT_V1_THEME_NAME, types: ["account"] diff --git a/src/bin/shared/buildContext.ts b/src/bin/shared/buildContext.ts index c970f420..e67df932 100644 --- a/src/bin/shared/buildContext.ts +++ b/src/bin/shared/buildContext.ts @@ -20,11 +20,9 @@ import type { KeycloakVersionRange } from "./KeycloakVersionRange"; import { exclude } from "tsafe"; import { crawl } from "../tools/crawl"; import { THEME_TYPES } from "./constants"; -import { objectFromEntries } from "tsafe/objectFromEntries"; import { objectEntries } from "tsafe/objectEntries"; import { type ThemeType } from "./constants"; import { id } from "tsafe/id"; -import { symToStr } from "tsafe/symToStr"; import chalk from "chalk"; import { getProxyFetchOptions, type ProxyFetchOptions } from "../tools/fetchProxyOptions"; @@ -49,11 +47,13 @@ export type BuildContext = { kcContextExclusionsFtlCode: string | undefined; environmentVariables: { name: string; default: string }[]; themeSrcDirPath: string; - recordIsImplementedByThemeType: Readonly>; - jarTargets: { - keycloakVersionRange: KeycloakVersionRange; - jarFileBasename: string; - }[]; + implementedThemeTypes: { + login: { isImplemented: boolean }; + email: { isImplemented: boolean }; + account: + | { isImplemented: false } + | { isImplemented: true; type: "Single-Page" | "Multi-Page" }; + }; bundler: | { type: "vite"; @@ -63,9 +63,14 @@ export type BuildContext = { packageJsonDirPath: string; packageJsonScripts: Record; }; - doUseAccountV3: boolean; + jarTargets: { + keycloakVersionRange: KeycloakVersionRange; + jarFileBasename: string; + }[]; }; +assert>(); + export type BuildOptions = { themeName?: string | string[]; themeVersion?: string; @@ -76,21 +81,30 @@ export type BuildOptions = { loginThemeResourcesFromKeycloakVersion?: string; keycloakifyBuildDirPath?: string; kcContextExclusionsFtl?: string; - /** https://docs.keycloakify.dev/v/v10/targetting-specific-keycloak-versions */ - keycloakVersionTargets?: BuildOptions.KeycloakVersionTargets; - doUseAccountV3?: boolean; -}; +} & BuildOptions.AccountThemeImplAndKeycloakVersionTargets; export namespace BuildOptions { - export type KeycloakVersionTargets = - | ({ hasAccountTheme: true } & Record< - KeycloakVersionRange.WithAccountV1Theme, - string | boolean - >) - | ({ hasAccountTheme: false } & Record< - KeycloakVersionRange.WithoutAccountV1Theme, - string | boolean - >); + export type AccountThemeImplAndKeycloakVersionTargets = + | AccountThemeImplAndKeycloakVersionTargets.MultiPageApp + | AccountThemeImplAndKeycloakVersionTargets.SinglePageAppOrNone; + + export namespace AccountThemeImplAndKeycloakVersionTargets { + export type MultiPageApp = { + accountThemeImplementation: "Multi-Page"; + keycloakVersionTargets?: Record< + KeycloakVersionRange.WithAccountV1Theme, + string | boolean + >; + }; + + export type SinglePageAppOrNone = { + accountThemeImplementation: "Single-Page" | "none"; + keycloakVersionTargets?: Record< + KeycloakVersionRange.WithoutAccountV1Theme, + string | boolean + >; + }; + } } export type ResolvedViteConfig = { @@ -231,7 +245,7 @@ export function getBuildContext(params: { projectBuildDirPath?: string; staticDirPathInProjectBuildDirPath?: string; publicDirPath?: string; - doUseAccountV3?: boolean; + scripts?: Record; }; type ParsedPackageJson = { @@ -241,85 +255,121 @@ export function getBuildContext(params: { keycloakify?: BuildOptions_packageJson; }; - const zParsedPackageJson = z.object({ - name: z.string().optional(), - version: z.string().optional(), - homepage: z.string().optional(), - keycloakify: id>( - (() => { - const zBuildOptions_packageJson = z.object({ - extraThemeProperties: z.array(z.string()).optional(), - artifactId: z.string().optional(), - groupId: z.string().optional(), - loginThemeResourcesFromKeycloakVersion: z.string().optional(), - projectBuildDirPath: z.string().optional(), - keycloakifyBuildDirPath: z.string().optional(), - kcContextExclusionsFtl: z.string().optional(), - environmentVariables: z - .array( - z.object({ - name: z.string(), - default: z.string() - }) - ) - .optional(), - themeName: z.union([z.string(), z.array(z.string())]).optional(), - themeVersion: z.string().optional(), - staticDirPathInProjectBuildDirPath: z.string().optional(), - publicDirPath: z.string().optional(), - keycloakVersionTargets: id< - z.ZodType - >( - (() => { - const zKeycloakVersionTargets = z.union([ - z.object({ - hasAccountTheme: z.literal(true), - "21-and-below": z.union([ - z.boolean(), - z.string() - ]), - "23": z.union([z.boolean(), z.string()]), - "24": z.union([z.boolean(), z.string()]), - "25-and-above": z.union([z.boolean(), z.string()]) - }), - z.object({ - hasAccountTheme: z.literal(false), - "21-and-below": z.union([ - z.boolean(), - z.string() - ]), - "22-and-above": z.union([z.boolean(), z.string()]) - }) - ]); + const zMultiPageApp = (() => { + type TargetType = + BuildOptions.AccountThemeImplAndKeycloakVersionTargets.MultiPageApp; - { - type Got = z.infer; - type Expected = BuildOptions.KeycloakVersionTargets; - assert>(); - } + const zTargetType = z.object({ + accountThemeImplementation: z.literal("Multi-Page"), + keycloakVersionTargets: z + .object({ + "21-and-below": z.union([z.boolean(), z.string()]), + "23": z.union([z.boolean(), z.string()]), + "24": z.union([z.boolean(), z.string()]), + "25-and-above": z.union([z.boolean(), z.string()]) + }) + .optional() + }); - return zKeycloakVersionTargets; - })() - ).optional(), - doUseAccountV3: z.boolean().optional() - }); + assert, TargetType>>(); - { - type Got = z.infer; - type Expected = BuildOptions_packageJson; - assert>(); - } + return id>(zTargetType); + })(); - return zBuildOptions_packageJson; - })() - ).optional() - }); + const zSinglePageApp = (() => { + type TargetType = + BuildOptions.AccountThemeImplAndKeycloakVersionTargets.SinglePageAppOrNone; - { - type Got = z.infer; - type Expected = ParsedPackageJson; - assert>(); - } + const zTargetType = z.object({ + accountThemeImplementation: z.union([ + z.literal("Single-Page"), + z.literal("none") + ]), + keycloakVersionTargets: z + .object({ + "21-and-below": z.union([z.boolean(), z.string()]), + "22-and-above": z.union([z.boolean(), z.string()]) + }) + .optional() + }); + + assert, TargetType>>(); + + return id>(zTargetType); + })(); + + const zAccountThemeImplAndKeycloakVersionTargets = (() => { + type TargetType = BuildOptions.AccountThemeImplAndKeycloakVersionTargets; + + const zTargetType = z.union([zMultiPageApp, zSinglePageApp]); + + assert, TargetType>>(); + + return id>(zTargetType); + })(); + + const zBuildOptions = (() => { + type TargetType = BuildOptions; + + const zTargetType = z.intersection( + z.object({ + themeName: z.union([z.string(), z.array(z.string())]).optional(), + themeVersion: z.string().optional(), + environmentVariables: z + .array( + z.object({ + name: z.string(), + default: z.string() + }) + ) + .optional(), + extraThemeProperties: z.array(z.string()).optional(), + artifactId: z.string().optional(), + groupId: z.string().optional(), + loginThemeResourcesFromKeycloakVersion: z.string().optional(), + keycloakifyBuildDirPath: z.string().optional(), + kcContextExclusionsFtl: z.string().optional() + }), + zAccountThemeImplAndKeycloakVersionTargets + ); + + assert, TargetType>>(); + + return id>(zTargetType); + })(); + + const zBuildOptions_packageJson = (() => { + type TargetType = BuildOptions_packageJson; + + const zTargetType = z.intersection( + zBuildOptions, + z.object({ + projectBuildDirPath: z.string().optional(), + staticDirPathInProjectBuildDirPath: z.string().optional(), + publicDirPath: z.string().optional(), + scripts: z.record(z.string()).optional() + }) + ); + + assert, TargetType>>(); + + return id>(zTargetType); + })(); + + const zParsedPackageJson = (() => { + type TargetType = ParsedPackageJson; + + const zTargetType = z.object({ + name: z.string().optional(), + version: z.string().optional(), + homepage: z.string().optional(), + keycloakify: zBuildOptions_packageJson.optional() + }); + + assert, TargetType>>(); + + return id>(zTargetType); + })(); const configurationPackageJsonFilePath = (() => { const rootPackageJsonFilePath = pathJoin(projectDirPath, "package.json"); @@ -334,17 +384,63 @@ export function getBuildContext(params: { ); })(); - const buildOptions = { - ...parsedPackageJson.keycloakify, - ...resolvedViteConfig?.buildOptions + const bundler = resolvedViteConfig !== undefined ? "vite" : "webpack"; + + if (bundler === "vite" && parsedPackageJson.keycloakify !== undefined) { + console.error( + chalk.red( + `In vite projects, provide your Keycloakify options in vite.config.ts, not in package.json` + ) + ); + process.exit(-1); + } + + const buildOptions: BuildOptions = (() => { + switch (bundler) { + case "vite": + assert(resolvedViteConfig !== undefined); + return resolvedViteConfig.buildOptions; + case "webpack": + assert(parsedPackageJson.keycloakify !== undefined); + return parsedPackageJson.keycloakify; + } + assert>(false); + })(); + + const implementedThemeTypes: BuildContext["implementedThemeTypes"] = { + login: { + isImplemented: fs.existsSync(pathJoin(themeSrcDirPath, "login")) + }, + email: { + isImplemented: fs.existsSync(pathJoin(themeSrcDirPath, "email")) + }, + account: (() => { + if (buildOptions.accountThemeImplementation === "none") { + return { isImplemented: false }; + } + + return { + isImplemented: true, + type: buildOptions.accountThemeImplementation + }; + })() }; - const recordIsImplementedByThemeType = objectFromEntries( - (["login", "account", "email"] as const).map(themeType => [ - themeType, - fs.existsSync(pathJoin(themeSrcDirPath, themeType)) - ]) - ); + if ( + implementedThemeTypes.account.isImplemented && + !fs.existsSync(pathJoin(themeSrcDirPath, "account")) + ) { + console.error( + chalk.red( + [ + `You have set 'accountThemeImplementation' to '${implementedThemeTypes.account.type}'`, + `but the 'account' directory is missing in your theme source directory`, + "Use the `npx keycloakify initialize-account-theme` command to create it" + ].join(" ") + ) + ); + process.exit(-1); + } const themeNames = ((): [string, ...string[]] => { if (buildOptions.themeName === undefined) { @@ -371,13 +467,15 @@ export function getBuildContext(params: { const projectBuildDirPath = (() => { webpack: { - if (resolvedViteConfig !== undefined) { + if (bundler !== "webpack") { break webpack; } - if (buildOptions.projectBuildDirPath !== undefined) { + assert(parsedPackageJson.keycloakify !== undefined); + + if (parsedPackageJson.keycloakify.projectBuildDirPath !== undefined) { return getAbsoluteAndInOsFormatPath({ - pathIsh: buildOptions.projectBuildDirPath, + pathIsh: parsedPackageJson.keycloakify.projectBuildDirPath, cwd: projectDirPath }); } @@ -385,34 +483,26 @@ export function getBuildContext(params: { return pathJoin(projectDirPath, "build"); } + assert(bundler === "vite"); + assert(resolvedViteConfig !== undefined); + return pathJoin(projectDirPath, resolvedViteConfig.buildDir); })(); - const bundler = resolvedViteConfig !== undefined ? "vite" : "webpack"; - - const doUseAccountV3 = buildOptions.doUseAccountV3 ?? false; - return { - bundler: - resolvedViteConfig !== undefined - ? { type: "vite" } - : (() => { - const { scripts } = z - .object({ - scripts: z.record(z.string()).optional() - }) - .parse( - JSON.parse( - fs.readFileSync(packageJsonFilePath).toString("utf8") - ) - ); - - return { - type: "webpack", - packageJsonDirPath: pathDirname(packageJsonFilePath), - packageJsonScripts: scripts ?? {} - }; - })(), + bundler: (() => { + switch (bundler) { + case "vite": + return { type: "vite" }; + case "webpack": + return { + type: "webpack", + packageJsonDirPath: pathDirname(packageJsonFilePath), + packageJsonScripts: parsedPackageJson.keycloakify?.scripts ?? {} + }; + } + assert>(false); + })(), themeVersion: buildOptions.themeVersion ?? parsedPackageJson.version ?? "0.0.0", themeNames, extraThemeProperties: buildOptions.extraThemeProperties, @@ -463,13 +553,15 @@ export function getBuildContext(params: { } webpack: { - if (resolvedViteConfig !== undefined) { + if (bundler !== "webpack") { break webpack; } - if (buildOptions.publicDirPath !== undefined) { + assert(parsedPackageJson.keycloakify !== undefined); + + if (parsedPackageJson.keycloakify.publicDirPath !== undefined) { return getAbsoluteAndInOsFormatPath({ - pathIsh: buildOptions.publicDirPath, + pathIsh: parsedPackageJson.keycloakify.publicDirPath, cwd: projectDirPath }); } @@ -477,6 +569,9 @@ export function getBuildContext(params: { return pathJoin(projectDirPath, "public"); } + assert(bundler === "vite"); + assert(resolvedViteConfig !== undefined); + return pathJoin(projectDirPath, resolvedViteConfig.publicDir); })(), cacheDirPath: (() => { @@ -502,7 +597,7 @@ export function getBuildContext(params: { })(), urlPathname: (() => { webpack: { - if (resolvedViteConfig !== undefined) { + if (bundler !== "webpack") { break webpack; } @@ -522,23 +617,35 @@ export function getBuildContext(params: { return out === "/" ? undefined : out; } + assert(bundler === "vite"); + assert(resolvedViteConfig !== undefined); + return resolvedViteConfig.urlPathname; })(), assetsDirPath: (() => { webpack: { - if (resolvedViteConfig !== undefined) { + if (bundler !== "webpack") { break webpack; } - if (buildOptions.staticDirPathInProjectBuildDirPath !== undefined) { + assert(parsedPackageJson.keycloakify !== undefined); + + if ( + parsedPackageJson.keycloakify.staticDirPathInProjectBuildDirPath !== + undefined + ) { getAbsoluteAndInOsFormatPath({ - pathIsh: buildOptions.staticDirPathInProjectBuildDirPath, + pathIsh: + parsedPackageJson.keycloakify + .staticDirPathInProjectBuildDirPath, cwd: projectBuildDirPath }); } return pathJoin(projectBuildDirPath, "static"); } + assert(bundler === "vite"); + assert(resolvedViteConfig !== undefined); return pathJoin(projectBuildDirPath, resolvedViteConfig.assetsDir); })(), @@ -559,7 +666,7 @@ export function getBuildContext(params: { return buildOptions.kcContextExclusionsFtl; })(), environmentVariables: buildOptions.environmentVariables ?? [], - recordIsImplementedByThemeType, + implementedThemeTypes, themeSrcDirPath, fetchOptions: getProxyFetchOptions({ npmConfigGetCwd: (function callee(upCount: number): string { @@ -613,10 +720,10 @@ export function getBuildContext(params: { } const keycloakVersionRange: KeycloakVersionRange = (() => { - const doesImplementAccountV1Theme = - !doUseAccountV3 && recordIsImplementedByThemeType.account; - - if (doesImplementAccountV1Theme) { + if ( + implementedThemeTypes.account.isImplemented && + implementedThemeTypes.account.type === "Multi-Page" + ) { const keycloakVersionRange = (() => { if (buildForKeycloakMajorVersionNumber <= 21) { return "21-and-below" as const; @@ -703,7 +810,10 @@ export function getBuildContext(params: { const jarTargets_default = (() => { const jarTargets: BuildContext["jarTargets"] = []; - if (!doUseAccountV3 && recordIsImplementedByThemeType.account) { + if ( + implementedThemeTypes.account.isImplemented && + implementedThemeTypes.account.type === "Multi-Page" + ) { for (const keycloakVersionRange of [ "21-and-below", "23", @@ -748,79 +858,11 @@ export function getBuildContext(params: { return jarTargets_default; } - if ( - buildOptions.keycloakVersionTargets.hasAccountTheme !== doUseAccountV3 - ? false - : recordIsImplementedByThemeType.account - ) { - console.log( - chalk.red( - (() => { - const { keycloakVersionTargets } = buildOptions; - - let message = `Bad ${symToStr({ keycloakVersionTargets })} configuration.\n`; - - if (keycloakVersionTargets.hasAccountTheme) { - message += - "Your codebase does not seem to implement an account theme "; - } else { - message += "Your codebase implements an account theme "; - } - - const { hasAccountTheme } = keycloakVersionTargets; - - message += `but you have set ${symToStr({ keycloakVersionTargets })}.${symToStr({ hasAccountTheme })}`; - message += ` to ${hasAccountTheme} in your `; - message += (() => { - switch (bundler) { - case "vite": - return "vite.config.ts"; - case "webpack": - return "package.json"; - } - assert>(false); - })(); - message += `. Please set it to ${!hasAccountTheme} `; - message += - "and fill up the relevant keycloak version ranges.\n"; - message += "Example:\n"; - message += JSON.stringify( - id>({ - keycloakVersionTargets: { - hasAccountTheme: - recordIsImplementedByThemeType.account, - ...objectFromEntries( - jarTargets_default.map( - ({ - keycloakVersionRange, - jarFileBasename - }) => [ - keycloakVersionRange, - jarFileBasename - ] - ) - ) - } - }), - null, - 2 - ); - message += - "\nSee: https://docs.keycloakify.dev/v/v10/targetting-specific-keycloak-versions"; - - return message; - })() - ) - ); - - process.exit(1); - } - const jarTargets: BuildContext["jarTargets"] = []; - const { hasAccountTheme, ...rest } = buildOptions.keycloakVersionTargets; - - for (const [keycloakVersionRange, jarNameOrBoolean] of objectEntries(rest)) { + for (const [keycloakVersionRange, jarNameOrBoolean] of objectEntries( + buildOptions.keycloakVersionTargets + )) { if (jarNameOrBoolean === false) { continue; } @@ -871,7 +913,6 @@ export function getBuildContext(params: { } return jarTargets; - })(), - doUseAccountV3 + })() }; } diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts index 7130969a..3c5214b2 100644 --- a/src/vite-plugin/vite-plugin.ts +++ b/src/vite-plugin/vite-plugin.ts @@ -18,12 +18,14 @@ import { import MagicString from "magic-string"; import { generateKcGenTs } from "../bin/shared/generateKcGenTs"; -export type Params = BuildOptions & { - postBuild?: (buildContext: Omit) => Promise; -}; +export namespace keycloakify { + export type Params = BuildOptions & { + postBuild?: (buildContext: Omit) => Promise; + }; +} -export function keycloakify(params?: Params) { - const { postBuild, ...buildOptions } = params ?? {}; +export function keycloakify(params: keycloakify.Params) { + const { postBuild, ...buildOptions } = params; let projectDirPath: string | undefined = undefined; let urlPathname: string | undefined = undefined;