Compare commits
14 Commits
v9.4.0-rc.
...
v9.4.0-rc.
Author | SHA1 | Date | |
---|---|---|---|
99bfd7379b | |||
5f257382fa | |||
e3e6847c82 | |||
4ee0823acb | |||
d466123b1c | |||
21cbc14a48 | |||
b2f2c3e386 | |||
b03340ed10 | |||
5b563d8e9b | |||
2790487fc7 | |||
ad5a368065 | |||
7c0a631a9a | |||
4a8920749a | |||
8ab118dd06 |
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "keycloakify",
|
"name": "keycloakify",
|
||||||
"version": "9.4.0-rc.11",
|
"version": "9.4.0-rc.16",
|
||||||
"description": "Create Keycloak themes using React",
|
"description": "Create Keycloak themes using React",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -119,7 +119,6 @@
|
|||||||
"make-fetch-happen": "^11.0.3",
|
"make-fetch-happen": "^11.0.3",
|
||||||
"minimal-polyfills": "^2.2.2",
|
"minimal-polyfills": "^2.2.2",
|
||||||
"minimist": "^1.2.6",
|
"minimist": "^1.2.6",
|
||||||
"path-browserify": "^1.0.1",
|
|
||||||
"react-markdown": "^5.0.3",
|
"react-markdown": "^5.0.3",
|
||||||
"recast": "^0.23.3",
|
"recast": "^0.23.3",
|
||||||
"rfc4648": "^1.5.2",
|
"rfc4648": "^1.5.2",
|
||||||
|
@ -81,8 +81,7 @@ async function main() {
|
|||||||
|
|
||||||
const generatedFileHeader = [
|
const generatedFileHeader = [
|
||||||
`//This code was automatically generated by running ${pathRelative(thisCodebaseRootDirPath, __filename)}`,
|
`//This code was automatically generated by running ${pathRelative(thisCodebaseRootDirPath, __filename)}`,
|
||||||
"//PLEASE DO NOT EDIT MANUALLY",
|
"//PLEASE DO NOT EDIT MANUALLY"
|
||||||
""
|
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
||||||
languages.forEach(language => {
|
languages.forEach(language => {
|
||||||
@ -95,6 +94,7 @@ async function main() {
|
|||||||
Buffer.from(
|
Buffer.from(
|
||||||
[
|
[
|
||||||
generatedFileHeader,
|
generatedFileHeader,
|
||||||
|
"",
|
||||||
"/* spell-checker: disable */",
|
"/* spell-checker: disable */",
|
||||||
`const messages= ${JSON.stringify(recordForPageType[language], null, 2)};`,
|
`const messages= ${JSON.stringify(recordForPageType[language], null, 2)};`,
|
||||||
"",
|
"",
|
||||||
@ -113,10 +113,15 @@ async function main() {
|
|||||||
Buffer.from(
|
Buffer.from(
|
||||||
[
|
[
|
||||||
generatedFileHeader,
|
generatedFileHeader,
|
||||||
|
`import * as en from "./en";`,
|
||||||
|
"",
|
||||||
"export async function getMessages(currentLanguageTag: string) {",
|
"export async function getMessages(currentLanguageTag: string) {",
|
||||||
" const { default: messages } = await (() => {",
|
" const { default: messages } = await (() => {",
|
||||||
" switch (currentLanguageTag) {",
|
" switch (currentLanguageTag) {",
|
||||||
...languages.map(language => ` case "${language}": return import("./${language}");`),
|
` case "en": return en;`,
|
||||||
|
...languages
|
||||||
|
.filter(language => language !== "en")
|
||||||
|
.map(language => ` case "${language}": return import("./${language}");`),
|
||||||
' default: return { "default": {} };',
|
' default: return { "default": {} };',
|
||||||
" }",
|
" }",
|
||||||
" })();",
|
" })();",
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import type { I18n } from "keycloakify/account/i18n";
|
import type { I18n } from "keycloakify/account/i18n";
|
||||||
import type { TemplateProps, ClassKey } from "keycloakify/account/TemplateProps";
|
import type { TemplateProps, ClassKey } from "keycloakify/account/TemplateProps";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
|
import type { KcContext } from "keycloakify/account/kcContext";
|
||||||
|
|
||||||
export type PageProps<KcContext, I18nExtended extends I18n> = {
|
export type PageProps<NarowedKcContext = KcContext, I18nExtended extends I18n = I18n> = {
|
||||||
Template: LazyOrNot<(props: TemplateProps<any, any>) => JSX.Element | null>;
|
Template: LazyOrNot<(props: TemplateProps<any, any>) => JSX.Element | null>;
|
||||||
kcContext: KcContext;
|
kcContext: NarowedKcContext;
|
||||||
i18n: I18nExtended;
|
i18n: I18nExtended;
|
||||||
doUseDefaultCss: boolean;
|
doUseDefaultCss: boolean;
|
||||||
classes?: Partial<Record<ClassKey, string>>;
|
classes?: Partial<Record<ClassKey, string>>;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { downloadKeycloakStaticResources, type BuildOptionsLike } from "./keycloakify/generateTheme/downloadKeycloakStaticResources";
|
import { downloadKeycloakStaticResources, type BuildOptionsLike } from "./keycloakify/generateTheme/downloadKeycloakStaticResources";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin, relative as pathRelative } from "path";
|
||||||
import { readBuildOptions } from "./keycloakify/buildOptions";
|
import { readBuildOptions } from "./keycloakify/buildOptions";
|
||||||
import { themeTypes, keycloak_resources, lastKeycloakVersionWithAccountV1 } from "./constants";
|
import { themeTypes, keycloak_resources, lastKeycloakVersionWithAccountV1 } from "./constants";
|
||||||
import { readThisNpmProjectVersion } from "./tools/readThisNpmProjectVersion";
|
import { readThisNpmProjectVersion } from "./tools/readThisNpmProjectVersion";
|
||||||
@ -19,6 +19,7 @@ export async function copyKeycloakResourcesToPublic(params: { processArgv: strin
|
|||||||
const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo");
|
const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo");
|
||||||
|
|
||||||
const { keycloakifyBuildinfoRaw } = generateKeycloakifyBuildinfoRaw({
|
const { keycloakifyBuildinfoRaw } = generateKeycloakifyBuildinfoRaw({
|
||||||
|
destDirPath,
|
||||||
"keycloakifyVersion": readThisNpmProjectVersion(),
|
"keycloakifyVersion": readThisNpmProjectVersion(),
|
||||||
buildOptions
|
buildOptions
|
||||||
});
|
});
|
||||||
@ -72,12 +73,13 @@ export async function copyKeycloakResourcesToPublic(params: { processArgv: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function generateKeycloakifyBuildinfoRaw(params: {
|
export function generateKeycloakifyBuildinfoRaw(params: {
|
||||||
|
destDirPath: string;
|
||||||
keycloakifyVersion: string;
|
keycloakifyVersion: string;
|
||||||
buildOptions: BuildOptionsLike & {
|
buildOptions: BuildOptionsLike & {
|
||||||
loginThemeResourcesFromKeycloakVersion: string;
|
loginThemeResourcesFromKeycloakVersion: string;
|
||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
const { keycloakifyVersion, buildOptions } = params;
|
const { destDirPath, keycloakifyVersion, buildOptions } = params;
|
||||||
|
|
||||||
const { cacheDirPath, npmWorkspaceRootDirPath, loginThemeResourcesFromKeycloakVersion, ...rest } = buildOptions;
|
const { cacheDirPath, npmWorkspaceRootDirPath, loginThemeResourcesFromKeycloakVersion, ...rest } = buildOptions;
|
||||||
|
|
||||||
@ -88,8 +90,8 @@ export function generateKeycloakifyBuildinfoRaw(params: {
|
|||||||
keycloakifyVersion,
|
keycloakifyVersion,
|
||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
loginThemeResourcesFromKeycloakVersion,
|
loginThemeResourcesFromKeycloakVersion,
|
||||||
cacheDirPath,
|
"cacheDirPath": pathRelative(destDirPath, cacheDirPath),
|
||||||
npmWorkspaceRootDirPath
|
"npmWorkspaceRootDirPath": pathRelative(destDirPath, npmWorkspaceRootDirPath)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
|
@ -20,6 +20,7 @@ import { readFieldNameUsage } from "./readFieldNameUsage";
|
|||||||
import { readExtraPagesNames } from "./readExtraPageNames";
|
import { readExtraPagesNames } from "./readExtraPageNames";
|
||||||
import { generateMessageProperties } from "./generateMessageProperties";
|
import { generateMessageProperties } from "./generateMessageProperties";
|
||||||
import { bringInAccountV1 } from "./bringInAccountV1";
|
import { bringInAccountV1 } from "./bringInAccountV1";
|
||||||
|
import { rmSync } from "../../tools/fs.rmSync";
|
||||||
|
|
||||||
export type BuildOptionsLike = {
|
export type BuildOptionsLike = {
|
||||||
bundler: "vite" | "webpack";
|
bundler: "vite" | "webpack";
|
||||||
@ -78,6 +79,11 @@ export async function generateTheme(params: {
|
|||||||
const themeTypeDirPath = getThemeTypeDirPath({ themeType });
|
const themeTypeDirPath = getThemeTypeDirPath({ themeType });
|
||||||
|
|
||||||
apply_replacers_and_move_to_theme_resources: {
|
apply_replacers_and_move_to_theme_resources: {
|
||||||
|
const destDirPath = pathJoin(themeTypeDirPath, "resources", basenameOfTheKeycloakifyResourcesDir);
|
||||||
|
|
||||||
|
// NOTE: Prevent accumulation of files in the assets dir, as names are hashed they pile up.
|
||||||
|
rmSync(destDirPath, { "recursive": true, "force": true });
|
||||||
|
|
||||||
if (themeType === "account" && implementedThemeTypes.login) {
|
if (themeType === "account" && implementedThemeTypes.login) {
|
||||||
// NOTE: We prevend doing it twice, it has been done for the login theme.
|
// NOTE: We prevend doing it twice, it has been done for the login theme.
|
||||||
|
|
||||||
@ -89,7 +95,7 @@ export async function generateTheme(params: {
|
|||||||
"resources",
|
"resources",
|
||||||
basenameOfTheKeycloakifyResourcesDir
|
basenameOfTheKeycloakifyResourcesDir
|
||||||
),
|
),
|
||||||
"destDirPath": pathJoin(themeTypeDirPath, "resources", basenameOfTheKeycloakifyResourcesDir)
|
destDirPath
|
||||||
});
|
});
|
||||||
|
|
||||||
break apply_replacers_and_move_to_theme_resources;
|
break apply_replacers_and_move_to_theme_resources;
|
||||||
@ -97,7 +103,7 @@ export async function generateTheme(params: {
|
|||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
"srcDirPath": buildOptions.reactAppBuildDirPath,
|
"srcDirPath": buildOptions.reactAppBuildDirPath,
|
||||||
"destDirPath": pathJoin(themeTypeDirPath, "resources", basenameOfTheKeycloakifyResourcesDir),
|
destDirPath,
|
||||||
"transformSourceCode": ({ filePath, sourceCode }) => {
|
"transformSourceCode": ({ filePath, sourceCode }) => {
|
||||||
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
||||||
// This should not happen if users follow the new instruction setup but we keep it for retrocompatibility.
|
// This should not happen if users follow the new instruction setup but we keep it for retrocompatibility.
|
||||||
|
@ -59,7 +59,7 @@ export async function main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const containerKeycloakVersion = "23.0.0";
|
const containerKeycloakVersion = "23.0.6";
|
||||||
|
|
||||||
generateStartKeycloakTestingContainer({
|
generateStartKeycloakTestingContainer({
|
||||||
"keycloakVersion": containerKeycloakVersion,
|
"keycloakVersion": containerKeycloakVersion,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import type { I18n } from "keycloakify/login/i18n";
|
import type { I18n } from "keycloakify/login/i18n";
|
||||||
import { type TemplateProps, type ClassKey } from "keycloakify/login/TemplateProps";
|
import { type TemplateProps, type ClassKey } from "keycloakify/login/TemplateProps";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
|
import type { KcContext } from "keycloakify/account/kcContext";
|
||||||
|
|
||||||
export type PageProps<KcContext, I18nExtended extends I18n> = {
|
export type PageProps<NarowedKcContext = KcContext, I18nExtended extends I18n = I18n> = {
|
||||||
Template: LazyOrNot<(props: TemplateProps<any, any>) => JSX.Element | null>;
|
Template: LazyOrNot<(props: TemplateProps<any, any>) => JSX.Element | null>;
|
||||||
kcContext: KcContext;
|
kcContext: NarowedKcContext;
|
||||||
i18n: I18nExtended;
|
i18n: I18nExtended;
|
||||||
doUseDefaultCss: boolean;
|
doUseDefaultCss: boolean;
|
||||||
classes?: Partial<Record<ClassKey, string>>;
|
classes?: Partial<Record<ClassKey, string>>;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { join as pathJoin, relative as pathRelative, sep as pathSep } from "path";
|
import { join as pathJoin, relative as pathRelative, sep as pathSep } from "path";
|
||||||
import type { Plugin } from "vite";
|
import type { Plugin } from "vite";
|
||||||
import { assert } from "tsafe/assert";
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { resolvedViteConfigJsonBasename, nameOfTheGlobal, basenameOfTheKeycloakifyResourcesDir, keycloak_resources } from "../bin/constants";
|
import { resolvedViteConfigJsonBasename, nameOfTheGlobal, basenameOfTheKeycloakifyResourcesDir, keycloak_resources } from "../bin/constants";
|
||||||
import type { ResolvedViteConfig } from "../bin/keycloakify/buildOptions/resolvedViteConfig";
|
import type { ResolvedViteConfig } from "../bin/keycloakify/buildOptions/resolvedViteConfig";
|
||||||
@ -9,20 +8,32 @@ import { replaceAll } from "../bin/tools/String.prototype.replaceAll";
|
|||||||
import { id } from "tsafe/id";
|
import { id } from "tsafe/id";
|
||||||
import { rm } from "../bin/tools/fs.rm";
|
import { rm } from "../bin/tools/fs.rm";
|
||||||
import { copyKeycloakResourcesToPublic } from "../bin/copy-keycloak-resources-to-public";
|
import { copyKeycloakResourcesToPublic } from "../bin/copy-keycloak-resources-to-public";
|
||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
|
||||||
export function keycloakify(): Plugin {
|
export function keycloakify() {
|
||||||
let reactAppRootDirPath: string | undefined = undefined;
|
let reactAppRootDirPath: string | undefined = undefined;
|
||||||
let urlPathname: string | undefined = undefined;
|
let urlPathname: string | undefined = undefined;
|
||||||
let buildDirPath: string | undefined = undefined;
|
let buildDirPath: string | undefined = undefined;
|
||||||
|
let command: "build" | "serve" | undefined = undefined;
|
||||||
|
|
||||||
return {
|
const plugin = {
|
||||||
"name": "keycloakify",
|
"name": "keycloakify" as const,
|
||||||
"apply": "build",
|
|
||||||
"configResolved": async resolvedConfig => {
|
"configResolved": async resolvedConfig => {
|
||||||
|
command = resolvedConfig.command;
|
||||||
|
|
||||||
reactAppRootDirPath = resolvedConfig.root;
|
reactAppRootDirPath = resolvedConfig.root;
|
||||||
urlPathname = (() => {
|
urlPathname = (() => {
|
||||||
let out = resolvedConfig.env.BASE_URL;
|
let out = resolvedConfig.env.BASE_URL;
|
||||||
|
|
||||||
|
if (out.startsWith(".") && command === "build") {
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
`BASE_URL=${out} is not supported By Keycloakify. Use an absolute URL instead.`,
|
||||||
|
`If this is a problem, please open an issue at https://github.com/keycloakify/keycloakify/issues/new`
|
||||||
|
].join("\n")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (out === undefined) {
|
if (out === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -45,7 +56,7 @@ export function keycloakify(): Plugin {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!fs.existsSync(cacheDirPath)) {
|
if (!fs.existsSync(cacheDirPath)) {
|
||||||
fs.mkdirSync(cacheDirPath);
|
fs.mkdirSync(cacheDirPath, { "recursive": true });
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
@ -70,6 +81,12 @@ export function keycloakify(): Plugin {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
"transform": (code, id) => {
|
"transform": (code, id) => {
|
||||||
|
assert(command !== undefined);
|
||||||
|
|
||||||
|
if (command !== "build") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(reactAppRootDirPath !== undefined);
|
assert(reactAppRootDirPath !== undefined);
|
||||||
|
|
||||||
let transformedCode: string | undefined = undefined;
|
let transformedCode: string | undefined = undefined;
|
||||||
@ -83,9 +100,8 @@ export function keycloakify(): Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isJavascriptFile = id.endsWith(".js") || id.endsWith(".jsx");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
const isJavascriptFile = id.endsWith(".js") || id.endsWith(".jsx");
|
||||||
const isTypeScriptFile = id.endsWith(".ts") || id.endsWith(".tsx");
|
const isTypeScriptFile = id.endsWith(".ts") || id.endsWith(".tsx");
|
||||||
|
|
||||||
if (!isTypeScriptFile && !isJavascriptFile) {
|
if (!isTypeScriptFile && !isJavascriptFile) {
|
||||||
@ -93,8 +109,6 @@ export function keycloakify(): Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const windowToken = isJavascriptFile ? "window" : "(window as any)";
|
|
||||||
|
|
||||||
if (transformedCode === undefined) {
|
if (transformedCode === undefined) {
|
||||||
transformedCode = code;
|
transformedCode = code;
|
||||||
}
|
}
|
||||||
@ -104,9 +118,9 @@ export function keycloakify(): Plugin {
|
|||||||
"import.meta.env.BASE_URL",
|
"import.meta.env.BASE_URL",
|
||||||
[
|
[
|
||||||
`(`,
|
`(`,
|
||||||
`(${windowToken}.${nameOfTheGlobal} === undefined || import.meta.env.MODE === "development") ?`,
|
`(window.${nameOfTheGlobal} === undefined || import.meta.env.MODE === "development")?`,
|
||||||
`"${urlPathname ?? "/"}":`,
|
`"${urlPathname ?? "/"}":`,
|
||||||
` \`\${${windowToken}.${nameOfTheGlobal}.url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/\``,
|
`(window.${nameOfTheGlobal}.url.resourcesPath + "/${basenameOfTheKeycloakifyResourcesDir}/")`,
|
||||||
`)`
|
`)`
|
||||||
].join("")
|
].join("")
|
||||||
);
|
);
|
||||||
@ -120,10 +134,18 @@ export function keycloakify(): Plugin {
|
|||||||
"code": transformedCode
|
"code": transformedCode
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
"buildEnd": async () => {
|
"closeBundle": async () => {
|
||||||
|
assert(command !== undefined);
|
||||||
|
|
||||||
|
if (command !== "build") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(buildDirPath !== undefined);
|
assert(buildDirPath !== undefined);
|
||||||
|
|
||||||
await rm(pathJoin(buildDirPath, keycloak_resources), { "recursive": true, "force": true });
|
await rm(pathJoin(buildDirPath, keycloak_resources), { "recursive": true, "force": true });
|
||||||
}
|
}
|
||||||
};
|
} satisfies Plugin;
|
||||||
|
|
||||||
|
return plugin as any;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user