Implement a mechanism to overload kcContext

This commit is contained in:
garronej
2021-06-28 04:04:48 +02:00
parent e160882db9
commit eac28f97b8
25 changed files with 604 additions and 48 deletions

View File

@ -1,7 +1,7 @@
import type { PageId } from "../../bin/build-keycloak-theme/generateFtl";
import type { KcLanguageTag } from "../i18n/KcLanguageTag";
import { doExtends } from "evt/tools/typeSafety/doExtends";
import { doExtends } from "tsafe/doExtends";
import type { MessageKey } from "../i18n/useKcMessage";
import type { LanguageLabel } from "../i18n/KcLanguageTag";
@ -150,7 +150,8 @@ export declare namespace KcContextBase {
pageId: "error.ftl";
client?: {
baseUrl?: string;
}
},
message: NonNullable<Common["message"]>;
};
export type LoginResetPassword = Common & {

View File

@ -1,28 +1,93 @@
import type { KcContextBase } from "./KcContextBase";
import type { KcContextBase } from "./KcContextBase";
import { kcContextMocks, kcContextCommonMock } from "./kcContextMocks";
import { ftlValuesGlobalName } from "../../bin/build-keycloak-theme/ftlValuesGlobalName";
import type { AndByDiscriminatingKey } from "../tools/AndByDiscriminatingKey";
import type { DeepPartial } from "../tools/DeepPartial";
import { deepAssign } from "../tools/deepAssign";
export function getKcContext<KcContextExtended extends { pageId: string; } = never>(
export type ExtendsKcContextBase<
KcContextExtended extends ({ pageId: string; } | undefined)
> =
KcContextExtended extends undefined ?
KcContextBase :
AndByDiscriminatingKey<
"pageId",
KcContextExtended & KcContextBase.Common,
KcContextBase
>;
export function getKcContext<KcContextExtended extends ({ pageId: string; } | undefined) = undefined>(
params?: {
mockPageId?: KcContextBase["pageId"] | KcContextExtended["pageId"];
kcContextExtendedMock?: KcContextExtended[];
mockPageId?: ExtendsKcContextBase<KcContextExtended>["pageId"];
mockData?: readonly DeepPartial<ExtendsKcContextBase<KcContextExtended>>[];
}
): { kcContext: (KcContextBase | KcContextExtended & KcContextBase.Common) | undefined; } {
): { kcContext: ExtendsKcContextBase<KcContextExtended> | undefined; } {
const { mockPageId, kcContextExtendedMock } = params ?? { "mockPageId": false };
const {
mockPageId,
mockData
} = params ?? {};
if (mockPageId !== undefined) {
return {
"pageId": mockPageId,
...(kcContextMocks.find(({ pageId }) => pageId === mockPageId) ?? kcContextCommonMock),
...(kcContextExtendedMock?.find(({ pageId }) => pageId === mockPageId) ?? {})
} as any;
//TODO maybe trow if no mock fo custom page
const kcContextDefaultMock = kcContextMocks.find(({ pageId }) => pageId === mockPageId);
const partialKcContextCustomMock = mockData?.find(({ pageId }) => pageId === mockPageId);
if (
kcContextDefaultMock === undefined &&
partialKcContextCustomMock === undefined
) {
console.warn([
`WARNING: You declared the non build in page ${mockPageId} but you didn't `,
`provide mock data needed to debug the page outside of Keycloak as you are trying to do now.`,
`Please check the documentation of the getKcContext function`
].join("\n"));
}
const kcContext: any = { "pageId": mockPageId };
deepAssign({
"target": kcContext,
"source": kcContextCommonMock
});
if (kcContextDefaultMock !== undefined) {
deepAssign({
"target": kcContext,
"source": kcContextDefaultMock
});
}
if (partialKcContextCustomMock !== undefined) {
deepAssign({
"target": kcContext,
"source": partialKcContextCustomMock
});
}
return { kcContext };
}
return (window as any)[ftlValuesGlobalName];
return {
"kcContext":
typeof window === "undefined" ?
undefined :
(window as any)[ftlValuesGlobalName]
};
}

View File

@ -5,12 +5,15 @@ import { getKcLanguageTagLabel } from "../../i18n/KcLanguageTag";
//NOTE: Aside because we want to be able to import them from node
import { resourcesCommonPath, resourcesPath } from "./urlResourcesPath";
import { id } from "tsafe/id";
import { join as pathJoin } from "path";
const PUBLIC_URL = process.env["PUBLIC_URL"] ?? "/";
export const kcContextCommonMock: KcContextBase.Common = {
"url": {
"loginAction": "#",
"resourcesPath": `${process.env["PUBLIC_URL"]}/${resourcesPath}`,
"resourcesCommonPath": `${process.env["PUBLIC_URL"]}/${resourcesCommonPath}`,
"resourcesPath": pathJoin(PUBLIC_URL, resourcesPath),
"resourcesCommonPath": pathJoin(PUBLIC_URL, resourcesCommonPath),
"loginRestartFlowUrl": "/auth/realms/myrealm/login-actions/restart?client_id=account&tab_id=HoAx28ja4xg",
"loginUrl": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg",
},
@ -95,7 +98,8 @@ export const kcContextCommonMock: KcContextBase.Common = {
"languageTag": "tr"
}
],
"current": null as any
//"current": null as any
"current": "English"
},
"auth": {
"showUsername": false,
@ -110,6 +114,7 @@ export const kcContextCommonMock: KcContextBase.Common = {
"isAppInitiatedAction": false,
};
Object.defineProperty(
kcContextCommonMock.locale!,
"current",
@ -188,6 +193,10 @@ export const kcContextMocks: KcContextBase[] = [
"pageId": "error.ftl",
"client": {
"baseUrl": "#"
},
"message": {
"type": "error",
"summary": "This is the error message"
}
}),
id<KcContextBase.LoginResetPassword>({

View File

@ -0,0 +1,43 @@
import { KcContextBase } from "./KcContextBase";
import type { AndByDiscriminatingKey } from "../tools/AndByDiscriminatingKey";
export type ExtendsKcContextBase<KcContextExtended extends { pageId: string; }>=
AndByDiscriminatingKey<
"pageId",
KcContextExtended & KcContextBase.Common,
KcContextBase
>;
type KcContextExtended =
{ pageId: "register.ftl"; authorizedMailDomains: string[]; } |
{ pageId: "my-extra-page-1.ftl"; } |
{ pageId: "my-extra-page-2.ftl"; someCustomValue: string; };
const y: ExtendsKcContextBase<KcContextExtended> = null as any;
if (y.pageId === "register.ftl") {
y.authorizedMailDomains;
y.realm.displayName;
y.register
}
if (y.pageId === "my-extra-page-1.ftl") {
y.realm.displayName;
}
if (y.pageId === "my-extra-page-2.ftl") {
y.realm
y.someCustomValue
}