Refactor completed

This commit is contained in:
garronej 2023-03-19 14:48:01 +01:00
parent 819f297de8
commit cd70d90914
16 changed files with 42 additions and 44 deletions

View File

@ -1,7 +1,7 @@
import { lazy, Suspense } from "react"; import { lazy, Suspense } from "react";
import type { KcContext } from "keycloakify/kcContext";
import type { PageProps } from "keycloakify/pages/PageProps"; import type { PageProps } from "keycloakify/pages/PageProps";
import type { I18n } from "keycloakify/i18n"; import type { I18n } from "keycloakify/i18n";
import type { KcContext } from "./kcContext";
const Login = lazy(() => import("keycloakify/pages/Login")); const Login = lazy(() => import("keycloakify/pages/Login"));
const Register = lazy(() => import("keycloakify/pages/Register")); const Register = lazy(() => import("keycloakify/pages/Register"));

View File

@ -3,7 +3,7 @@ import { clsx } from "keycloakify/tools/clsx";
import { usePrepareTemplate } from "keycloakify/lib/usePrepareTemplate"; import { usePrepareTemplate } from "keycloakify/lib/usePrepareTemplate";
import { type TemplateProps, defaultTemplateClasses } from "keycloakify/TemplateProps"; import { type TemplateProps, defaultTemplateClasses } from "keycloakify/TemplateProps";
import { useGetClassName } from "keycloakify/lib/useGetClassName"; import { useGetClassName } from "keycloakify/lib/useGetClassName";
type KcContext = import("./kcContext/KcContext").KcContext.Common; import type { KcContext } from "./kcContext";
import type { I18n } from "./i18n"; import type { I18n } from "./i18n";
export default function Template(props: TemplateProps<KcContext, I18n>) { export default function Template(props: TemplateProps<KcContext, I18n>) {

View File

@ -1,6 +1,6 @@
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import type { KcContext } from "keycloakify/kcContext"; import type { KcContext } from "./kcContext";
import type { I18n } from "keycloakify/i18n"; import type { I18n } from "./i18n";
export type TemplateProps<KcContext extends KcContext.Common, I18nExtended extends I18n> = { export type TemplateProps<KcContext extends KcContext.Common, I18nExtended extends I18n> = {
kcContext: KcContext; kcContext: KcContext;

View File

@ -17,7 +17,7 @@ export type KcContextLike = {
assert<KcContext extends KcContextLike ? true : false>(); assert<KcContext extends KcContextLike ? true : false>();
export type MessageKeyBase = keyof typeof baseMessages | keyof (typeof keycloakifyExtraMessages)[typeof fallbackLanguageTag]; export type MessageKey = keyof typeof baseMessages | keyof (typeof keycloakifyExtraMessages)[typeof fallbackLanguageTag];
export type GenericI18n<MessageKey extends string> = { export type GenericI18n<MessageKey extends string> = {
/** /**
@ -67,15 +67,15 @@ export type GenericI18n<MessageKey extends string> = {
advancedMsgStr: (key: string, ...args: (string | undefined)[]) => string; advancedMsgStr: (key: string, ...args: (string | undefined)[]) => string;
}; };
export type I18n = GenericI18n<MessageKeyBase>; export type I18n = GenericI18n<MessageKey>;
export function createUseI18n<ExtraMessageKey extends string = never>(extraMessages: { export function createUseI18n<ExtraMessageKey extends string = never>(extraMessages: {
[languageTag: string]: { [key in ExtraMessageKey]: string }; [languageTag: string]: { [key in ExtraMessageKey]: string };
}) { }) {
function useI18n(params: { kcContext: KcContextLike }): GenericI18n<MessageKeyBase | ExtraMessageKey> | null { function useI18n(params: { kcContext: KcContextLike }): GenericI18n<MessageKey | ExtraMessageKey> | null {
const { kcContext } = params; const { kcContext } = params;
const [i18n, setI18n] = useState<GenericI18n<ExtraMessageKey | MessageKeyBase> | undefined>(undefined); const [i18n, setI18n] = useState<GenericI18n<ExtraMessageKey | MessageKey> | undefined>(undefined);
const refHasStartedFetching = useRef(false); const refHasStartedFetching = useRef(false);

1
src/i18n/index.ts Normal file
View File

@ -0,0 +1 @@
export type { I18n } from "./i18n";

View File

@ -1 +0,0 @@
export * from "./i18n";

View File

@ -5,6 +5,6 @@ export default Fallback;
export { createKeycloakAdapter } from "keycloakify/lib/keycloakJsAdapter"; export { createKeycloakAdapter } from "keycloakify/lib/keycloakJsAdapter";
export { useDownloadTerms } from "keycloakify/lib/useDownloadTerms"; export { useDownloadTerms } from "keycloakify/lib/useDownloadTerms";
export { getKcContext } from "keycloakify/kcContext/getKcContext"; export { getKcContext } from "keycloakify/kcContext/getKcContext";
export { createUseI18n } from "keycloakify/i18n"; export { createUseI18n } from "keycloakify/i18n/i18n";
export type { PageProps } from "keycloakify/pages/PageProps"; export type { PageProps } from "keycloakify/pages/PageProps";

View File

@ -1,7 +1,7 @@
import type { PageId } from "../bin/keycloakify/generateFtl"; import type { PageId } from "../bin/keycloakify/generateFtl";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import type { Equals } from "tsafe"; import type { Equals } from "tsafe";
import type { MessageKeyBase } from "../i18n"; import type { MessageKey } from "../i18n/i18n";
type ExtractAfterStartingWith<Prefix extends string, StrEnum> = StrEnum extends `${Prefix}${infer U}` ? U : never; type ExtractAfterStartingWith<Prefix extends string, StrEnum> = StrEnum extends `${Prefix}${infer U}` ? U : never;
@ -160,7 +160,7 @@ export declare namespace KcContext {
export type Info = Common & { export type Info = Common & {
pageId: "info.ftl"; pageId: "info.ftl";
messageHeader?: string; messageHeader?: string;
requiredActions?: ExtractAfterStartingWith<"requiredAction.", MessageKeyBase>[]; requiredActions?: ExtractAfterStartingWith<"requiredAction.", MessageKey>[];
skipLink: boolean; skipLink: boolean;
pageRedirectUri?: string; pageRedirectUri?: string;
actionUri?: string; actionUri?: string;
@ -279,7 +279,7 @@ export declare namespace KcContext {
credentialId: string; credentialId: string;
transports: { transports: {
iconClass: string; iconClass: string;
displayNameProperties: MessageKeyBase[]; displayNameProperties: MessageKey[];
}; };
label: string; label: string;
createdAt: string; createdAt: string;

View File

@ -5,7 +5,7 @@ import { deepAssign } from "../tools/deepAssign";
import { id } from "tsafe/id"; import { id } from "tsafe/id";
import { exclude } from "tsafe/exclude"; import { exclude } from "tsafe/exclude";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import type { ExtendsKcContext } from "./getKcContextFromWindow"; import type { ExtendKcContext } from "./getKcContextFromWindow";
import { getKcContextFromWindow } from "./getKcContextFromWindow"; import { getKcContextFromWindow } from "./getKcContextFromWindow";
import { pathJoin } from "../bin/tools/pathJoin"; import { pathJoin } from "../bin/tools/pathJoin";
import { pathBasename } from "../tools/pathBasename"; import { pathBasename } from "../tools/pathBasename";
@ -13,9 +13,9 @@ import { mockTestingResourcesCommonPath } from "../bin/mockTestingResourcesPath"
import { symToStr } from "tsafe/symToStr"; import { symToStr } from "tsafe/symToStr";
export function getKcContext<KcContextExtension extends { pageId: string } = never>(params?: { export function getKcContext<KcContextExtension extends { pageId: string } = never>(params?: {
mockPageId?: ExtendsKcContext<KcContextExtension>["pageId"]; mockPageId?: ExtendKcContext<KcContextExtension>["pageId"];
mockData?: readonly DeepPartial<ExtendsKcContext<KcContextExtension>>[]; mockData?: readonly DeepPartial<ExtendKcContext<KcContextExtension>>[];
}): { kcContext: ExtendsKcContext<KcContextExtension> | undefined } { }): { kcContext: ExtendKcContext<KcContextExtension> | undefined } {
const { mockPageId, mockData } = params ?? {}; const { mockPageId, mockData } = params ?? {};
const realKcContext = getKcContextFromWindow<KcContextExtension>(); const realKcContext = getKcContextFromWindow<KcContextExtension>();

View File

@ -2,10 +2,10 @@ import type { KcContext } from "./KcContext";
import type { AndByDiscriminatingKey } from "../tools/AndByDiscriminatingKey"; import type { AndByDiscriminatingKey } from "../tools/AndByDiscriminatingKey";
import { ftlValuesGlobalName } from "../bin/keycloakify/ftlValuesGlobalName"; import { ftlValuesGlobalName } from "../bin/keycloakify/ftlValuesGlobalName";
export type ExtendsKcContext<KcContextExtension extends { pageId: string }> = [KcContextExtension] extends [never] export type ExtendKcContext<KcContextExtension extends { pageId: string }> = [KcContextExtension] extends [never]
? KcContext ? KcContext
: AndByDiscriminatingKey<"pageId", KcContextExtension & KcContext.Common, KcContext>; : AndByDiscriminatingKey<"pageId", KcContextExtension & KcContext.Common, KcContext>;
export function getKcContextFromWindow<KcContextExtension extends { pageId: string } = never>(): ExtendsKcContext<KcContextExtension> | undefined { export function getKcContextFromWindow<KcContextExtension extends { pageId: string } = never>(): ExtendKcContext<KcContextExtension> | undefined {
return typeof window === "undefined" ? undefined : (window as any)[ftlValuesGlobalName]; return typeof window === "undefined" ? undefined : (window as any)[ftlValuesGlobalName];
} }

View File

@ -1,3 +1 @@
export type { KcContext, Attribute, Validators } from "./KcContext"; export type { KcContext } from "./KcContext";
export type { ExtendsKcContext } from "./getKcContextFromWindow";
export { getKcContext } from "./getKcContext";

View File

@ -1,11 +1,11 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { memoize } from "../tools/memoize"; import { memoize } from "keycloakify/tools/memoize";
import { fallbackLanguageTag } from "../i18n"; import { fallbackLanguageTag } from "keycloakify/i18n/i18n";
import { useConst } from "../tools/useConst"; import { useConst } from "keycloakify/tools/useConst";
import { useConstCallback } from "../tools/useConstCallback"; import { useConstCallback } from "keycloakify/tools/useConstCallback";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { KcContext } from "../kcContext";
import { Evt } from "evt"; import { Evt } from "evt";
import { KcContext } from "../kcContext";
export const evtTermMarkdown = Evt.create<string | undefined>(undefined); export const evtTermMarkdown = Evt.create<string | undefined>(undefined);

View File

@ -1,8 +1,8 @@
import "keycloakify/tools/Array.prototype.every"; import "keycloakify/tools/Array.prototype.every";
import { useMemo, useReducer, Fragment } from "react"; import { useMemo, useReducer, Fragment } from "react";
import { id } from "tsafe/id"; import { id } from "tsafe/id";
import type { MessageKeyBase } from "keycloakify/i18n"; import type { MessageKey } from "keycloakify/i18n/i18n";
import type { Attribute, Validators } from "keycloakify/kcContext"; import type { Attribute, Validators } from "keycloakify/kcContext/KcContext";
import { useConstCallback } from "keycloakify/tools/useConstCallback"; import { useConstCallback } from "keycloakify/tools/useConstCallback";
import { emailRegexp } from "keycloakify/tools/emailRegExp"; import { emailRegexp } from "keycloakify/tools/emailRegExp";
import type { KcContext } from "../kcContext"; import type { KcContext } from "../kcContext";
@ -52,7 +52,7 @@ export function useFormValidation(params: {
curr, curr,
id<Attribute>({ id<Attribute>({
"name": "password", "name": "password",
"displayName": id<`\${${MessageKeyBase}}`>("${password}"), "displayName": id<`\${${MessageKey}}`>("${password}"),
"required": true, "required": true,
"readOnly": false, "readOnly": false,
"validators": passwordValidators, "validators": passwordValidators,
@ -62,7 +62,7 @@ export function useFormValidation(params: {
}), }),
id<Attribute>({ id<Attribute>({
"name": "password-confirm", "name": "password-confirm",
"displayName": id<`\${${MessageKeyBase}}`>("${passwordConfirm}"), "displayName": id<`\${${MessageKey}}`>("${passwordConfirm}"),
"required": true, "required": true,
"readOnly": false, "readOnly": false,
"validators": { "validators": {
@ -70,7 +70,7 @@ export function useFormValidation(params: {
"name": "password", "name": "password",
"ignore.empty.value": true, "ignore.empty.value": true,
"shouldBe": "equal", "shouldBe": "equal",
"error-message": id<`\${${MessageKeyBase}}`>("${invalidPasswordConfirmMessage}") "error-message": id<`\${${MessageKey}}`>("${invalidPasswordConfirmMessage}")
} }
}, },
"annotations": {}, "annotations": {},
@ -312,7 +312,7 @@ function useGetErrors(params: {
const msgArg = [ const msgArg = [
errorMessageKey ?? errorMessageKey ??
id<MessageKeyBase>( id<MessageKey>(
(() => { (() => {
switch (shouldBe) { switch (shouldBe) {
case "equal": case "equal":
@ -353,7 +353,7 @@ function useGetErrors(params: {
break scope; break scope;
} }
const msgArgs = [errorMessageKey ?? id<MessageKeyBase>("shouldMatchPattern"), pattern] as const; const msgArgs = [errorMessageKey ?? id<MessageKey>("shouldMatchPattern"), pattern] as const;
errors.push({ errors.push({
validatorName, validatorName,
@ -385,7 +385,7 @@ function useGetErrors(params: {
break scope; break scope;
} }
const msgArgs = [id<MessageKeyBase>("invalidEmailMessage")] as const; const msgArgs = [id<MessageKey>("invalidEmailMessage")] as const;
errors.push({ errors.push({
validatorName, validatorName,
@ -465,7 +465,7 @@ function useGetErrors(params: {
break scope; break scope;
} }
const msgArgs = [id<MessageKeyBase>("notAValidOption")] as const; const msgArgs = [id<MessageKey>("notAValidOption")] as const;
errors.push({ errors.push({
validatorName, validatorName,

View File

@ -1,6 +1,6 @@
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { clsx } from "keycloakify/tools/clsx"; import { clsx } from "keycloakify/tools/clsx";
import type { MessageKeyBase } from "../i18n"; import type { MessageKey } from "../i18n/i18n";
import { base64url } from "rfc4648"; import { base64url } from "rfc4648";
import { useConstCallback } from "../tools/useConstCallback"; import { useConstCallback } from "../tools/useConstCallback";
import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps";
@ -158,7 +158,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
className={getClassName("kcSelectAuthListItemDescriptionClass")} className={getClassName("kcSelectAuthListItemDescriptionClass")}
> >
{authenticator.transports.displayNameProperties.map( {authenticator.transports.displayNameProperties.map(
(transport: MessageKeyBase, index: number) => ( (transport: MessageKey, index: number) => (
<> <>
<span>{msg(transport)}</span> <span>{msg(transport)}</span>
{index < authenticator.transports.displayNameProperties.length - 1 && ( {index < authenticator.transports.displayNameProperties.length - 1 && (

View File

@ -2,7 +2,7 @@ import { useEffect, Fragment } from "react";
import type { ClassKey } from "keycloakify/pages/PageProps"; import type { ClassKey } from "keycloakify/pages/PageProps";
import { clsx } from "keycloakify/tools/clsx"; import { clsx } from "keycloakify/tools/clsx";
import { useFormValidation } from "keycloakify/lib/useFormValidation"; import { useFormValidation } from "keycloakify/lib/useFormValidation";
import type { Attribute } from "keycloakify/kcContext"; import type { Attribute } from "keycloakify/kcContext/KcContext";
import type { I18n } from "../../i18n"; import type { I18n } from "../../i18n";
export type UserProfileFormFieldsProps = { export type UserProfileFormFieldsProps = {

View File

@ -1,6 +1,6 @@
import { getKcContext } from "../../src/kcContext"; import { getKcContext } from "../../src/kcContext/getKcContext";
import type { ExtendKcContext } from "../../src/kcContext/getKcContextFromWindow";
import type { KcContext } from "../../src/kcContext"; import type { KcContext } from "../../src/kcContext";
import type { ExtendsKcContext } from "../../src/kcContext";
import { same } from "evt/tools/inDepth"; import { same } from "evt/tools/inDepth";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import type { Equals } from "tsafe"; import type { Equals } from "tsafe";
@ -15,7 +15,7 @@ import { deepClone } from "../../src/tools/deepClone";
const aNonStandardValue1 = "a non standard value 1"; const aNonStandardValue1 = "a non standard value 1";
const aNonStandardValue2 = "a non standard value 2"; const aNonStandardValue2 = "a non standard value 2";
type KcContextExtended = type KcContextExtension =
| { | {
pageId: "register.ftl"; pageId: "register.ftl";
authorizedMailDomains: string[]; authorizedMailDomains: string[];
@ -32,10 +32,10 @@ import { deepClone } from "../../src/tools/deepClone";
aNonStandardValue2: string; aNonStandardValue2: string;
}; };
const getKcContextProxy = (params: { mockPageId: ExtendsKcContext<KcContextExtended>["pageId"] }) => { const getKcContextProxy = (params: { mockPageId: ExtendKcContext<KcContextExtension>["pageId"] }) => {
const { mockPageId } = params; const { mockPageId } = params;
const { kcContext } = getKcContext<KcContextExtended>({ const { kcContext } = getKcContext<KcContextExtension>({
mockPageId, mockPageId,
"mockData": [ "mockData": [
{ {