keycloakify 10.0.0-rc.23 → 10.0.0-rc.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/PUBLIC_URL.d.ts +1 -1
  2. package/PUBLIC_URL.js +1 -1
  3. package/PUBLIC_URL.js.map +1 -1
  4. package/account/Fallback.js.map +1 -1
  5. package/account/Template.js +3 -3
  6. package/account/Template.js.map +1 -1
  7. package/account/i18n/baseMessages/index.js.map +1 -1
  8. package/account/i18n/i18n.js.map +1 -1
  9. package/account/index.d.ts +2 -2
  10. package/account/index.js +1 -2
  11. package/account/index.js.map +1 -1
  12. package/account/kcContext/KcContext.d.ts +12 -0
  13. package/account/kcContext/KcContext.js.map +1 -1
  14. package/account/kcContext/getKcContextMock.d.ts +24 -0
  15. package/account/kcContext/getKcContextMock.js +28 -0
  16. package/account/kcContext/getKcContextMock.js.map +1 -0
  17. package/account/kcContext/index.d.ts +2 -1
  18. package/account/kcContext/index.js +1 -1
  19. package/account/kcContext/index.js.map +1 -1
  20. package/account/kcContext/kcContextMocks.js +23 -91
  21. package/account/kcContext/kcContextMocks.js.map +1 -1
  22. package/account/pages/Account.js +1 -1
  23. package/account/pages/Account.js.map +1 -1
  24. package/account/pages/Applications.js +2 -2
  25. package/account/pages/Applications.js.map +1 -1
  26. package/account/pages/FederatedIdentity.js +1 -1
  27. package/account/pages/FederatedIdentity.js.map +1 -1
  28. package/account/pages/Log.js +1 -1
  29. package/account/pages/Log.js.map +1 -1
  30. package/account/pages/Password.js +6 -4
  31. package/account/pages/Password.js.map +1 -1
  32. package/account/pages/Sessions.js +1 -1
  33. package/account/pages/Sessions.js.map +1 -1
  34. package/account/pages/Totp.js +1 -1
  35. package/account/pages/Totp.js.map +1 -1
  36. package/bin/main.js +152 -162
  37. package/lib/BASE_URL.js.map +1 -1
  38. package/login/Fallback.js.map +1 -1
  39. package/login/Template.js +7 -7
  40. package/login/Template.js.map +1 -1
  41. package/login/UserProfileFormFields.js +24 -68
  42. package/login/UserProfileFormFields.js.map +1 -1
  43. package/login/i18n/baseMessages/index.js.map +1 -1
  44. package/login/i18n/i18n.js.map +1 -1
  45. package/login/index.d.ts +2 -3
  46. package/login/index.js +1 -2
  47. package/login/index.js.map +1 -1
  48. package/login/kcContext/KcContext.d.ts +23 -12
  49. package/login/kcContext/KcContext.js.map +1 -1
  50. package/login/kcContext/getKcContextMock.d.ts +24 -0
  51. package/login/kcContext/getKcContextMock.js +28 -0
  52. package/login/kcContext/getKcContextMock.js.map +1 -0
  53. package/login/kcContext/index.d.ts +2 -1
  54. package/login/kcContext/index.js +1 -1
  55. package/login/kcContext/index.js.map +1 -1
  56. package/login/kcContext/kcContextMocks.js +32 -99
  57. package/login/kcContext/kcContextMocks.js.map +1 -1
  58. package/login/lib/useDownloadTerms.js +8 -14
  59. package/login/lib/useDownloadTerms.js.map +1 -1
  60. package/login/lib/useGetClassName.js +1 -1
  61. package/login/lib/useGetClassName.js.map +1 -1
  62. package/login/lib/useUserProfileForm.d.ts +9 -1
  63. package/login/lib/useUserProfileForm.js +94 -15
  64. package/login/lib/useUserProfileForm.js.map +1 -1
  65. package/login/pages/Code.js +1 -1
  66. package/login/pages/Code.js.map +1 -1
  67. package/login/pages/DeleteAccountConfirm.js +2 -2
  68. package/login/pages/DeleteAccountConfirm.js.map +1 -1
  69. package/login/pages/DeleteCredential.js +1 -1
  70. package/login/pages/DeleteCredential.js.map +1 -1
  71. package/login/pages/Error.js +1 -1
  72. package/login/pages/Error.js.map +1 -1
  73. package/login/pages/FrontchannelLogout.js +1 -1
  74. package/login/pages/FrontchannelLogout.js.map +1 -1
  75. package/login/pages/IdpReviewUserProfile.js +1 -1
  76. package/login/pages/IdpReviewUserProfile.js.map +1 -1
  77. package/login/pages/Info.js +5 -5
  78. package/login/pages/Info.js.map +1 -1
  79. package/login/pages/Login.js +4 -4
  80. package/login/pages/Login.js.map +1 -1
  81. package/login/pages/LoginConfigTotp.js +2 -2
  82. package/login/pages/LoginConfigTotp.js.map +1 -1
  83. package/login/pages/LoginIdpLinkConfirm.js +1 -1
  84. package/login/pages/LoginIdpLinkConfirm.js.map +1 -1
  85. package/login/pages/LoginIdpLinkEmail.js +1 -1
  86. package/login/pages/LoginIdpLinkEmail.js.map +1 -1
  87. package/login/pages/LoginOauth2DeviceVerifyUserCode.js +1 -1
  88. package/login/pages/LoginOauth2DeviceVerifyUserCode.js.map +1 -1
  89. package/login/pages/LoginOauthGrant.js +2 -2
  90. package/login/pages/LoginOauthGrant.js.map +1 -1
  91. package/login/pages/LoginOtp.js +1 -1
  92. package/login/pages/LoginOtp.js.map +1 -1
  93. package/login/pages/LoginPageExpired.js +1 -1
  94. package/login/pages/LoginPageExpired.js.map +1 -1
  95. package/login/pages/LoginPassword.js +3 -3
  96. package/login/pages/LoginPassword.js.map +1 -1
  97. package/login/pages/LoginRecoveryAuthnCodeConfig.js +10 -10
  98. package/login/pages/LoginRecoveryAuthnCodeConfig.js.map +1 -1
  99. package/login/pages/LoginRecoveryAuthnCodeInput.js +1 -1
  100. package/login/pages/LoginRecoveryAuthnCodeInput.js.map +1 -1
  101. package/login/pages/LoginResetOtp.js +1 -1
  102. package/login/pages/LoginResetOtp.js.map +1 -1
  103. package/login/pages/LoginResetPassword.js +2 -2
  104. package/login/pages/LoginResetPassword.js.map +1 -1
  105. package/login/pages/LoginUpdatePassword.js +3 -3
  106. package/login/pages/LoginUpdatePassword.js.map +1 -1
  107. package/login/pages/LoginUpdateProfile.js +4 -2
  108. package/login/pages/LoginUpdateProfile.js.map +1 -1
  109. package/login/pages/LoginUsername.js +3 -3
  110. package/login/pages/LoginUsername.js.map +1 -1
  111. package/login/pages/LoginVerifyEmail.js +1 -1
  112. package/login/pages/LoginVerifyEmail.js.map +1 -1
  113. package/login/pages/LoginX509Info.js +1 -1
  114. package/login/pages/LoginX509Info.js.map +1 -1
  115. package/login/pages/LogoutConfirm.js +1 -1
  116. package/login/pages/LogoutConfirm.js.map +1 -1
  117. package/login/pages/Register.js +8 -4
  118. package/login/pages/Register.js.map +1 -1
  119. package/login/pages/SamlPostForm.js +1 -1
  120. package/login/pages/SamlPostForm.js.map +1 -1
  121. package/login/pages/SelectAuthenticator.js +2 -2
  122. package/login/pages/SelectAuthenticator.js.map +1 -1
  123. package/login/pages/Terms.js +1 -1
  124. package/login/pages/Terms.js.map +1 -1
  125. package/login/pages/UpdateEmail.js +5 -3
  126. package/login/pages/UpdateEmail.js.map +1 -1
  127. package/login/pages/WebauthnAuthenticate.js +8 -8
  128. package/login/pages/WebauthnAuthenticate.js.map +1 -1
  129. package/login/pages/WebauthnError.js +2 -2
  130. package/login/pages/WebauthnError.js.map +1 -1
  131. package/login/pages/WebauthnRegister.js +5 -5
  132. package/login/pages/WebauthnRegister.js.map +1 -1
  133. package/package.json +26 -38
  134. package/src/PUBLIC_URL.ts +1 -1
  135. package/src/account/Template.tsx +2 -3
  136. package/src/account/index.ts +2 -2
  137. package/src/account/kcContext/KcContext.ts +19 -1
  138. package/src/account/kcContext/getKcContextMock.ts +80 -0
  139. package/src/account/kcContext/index.ts +2 -1
  140. package/src/account/kcContext/kcContextMocks.ts +26 -91
  141. package/src/bin/copy-keycloak-resources-to-public.ts +1 -4
  142. package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +4 -6
  143. package/src/bin/tools/getNpmWorkspaceRootDirPath.ts +25 -25
  144. package/src/login/Template.tsx +4 -5
  145. package/src/login/UserProfileFormFields.tsx +28 -80
  146. package/src/login/index.ts +6 -3
  147. package/src/login/kcContext/KcContext.ts +41 -27
  148. package/src/login/kcContext/getKcContextMock.ts +80 -0
  149. package/src/login/kcContext/index.ts +7 -1
  150. package/src/login/kcContext/kcContextMocks.ts +95 -156
  151. package/src/login/lib/useDownloadTerms.ts +10 -24
  152. package/src/login/lib/useGetClassName.ts +1 -1
  153. package/src/login/lib/useUserProfileForm.tsx +117 -13
  154. package/src/login/pages/LoginConfigTotp.tsx +1 -1
  155. package/src/login/pages/LoginRecoveryAuthnCodeConfig.tsx +7 -8
  156. package/src/login/pages/WebauthnAuthenticate.tsx +2 -3
  157. package/src/login/pages/WebauthnRegister.tsx +2 -3
  158. package/src/tools/ExtractAfterStartingWith.ts +4 -0
  159. package/src/tools/StatefulObservable/hooks/useRerenderOnChange.ts +4 -4
  160. package/src/tools/ValueOf.ts +2 -0
  161. package/src/tools/deepAssign.ts +51 -20
  162. package/src/tools/structuredCloneButFunctions.ts +24 -0
  163. package/src/tools/useInsertLinkTags.ts +78 -87
  164. package/src/tools/useInsertScriptTags.ts +69 -78
  165. package/src/tools/useOnFirstMount.ts +18 -0
  166. package/tools/Array.prototype.every.js.map +1 -1
  167. package/tools/ExtractAfterStartingWith.d.ts +1 -0
  168. package/tools/ExtractAfterStartingWith.js +2 -0
  169. package/tools/ExtractAfterStartingWith.js.map +1 -0
  170. package/tools/HTMLElement.prototype.prepend.js.map +1 -1
  171. package/tools/StatefulObservable/StatefulObservable.js.map +1 -1
  172. package/tools/StatefulObservable/hooks/useRerenderOnChange.d.ts +1 -1
  173. package/tools/StatefulObservable/hooks/useRerenderOnChange.js +4 -4
  174. package/tools/StatefulObservable/hooks/useRerenderOnChange.js.map +1 -1
  175. package/tools/ValueOf.d.ts +2 -0
  176. package/tools/ValueOf.js +2 -0
  177. package/tools/ValueOf.js.map +1 -0
  178. package/tools/clsx.js.map +1 -1
  179. package/tools/deepAssign.d.ts +1 -0
  180. package/tools/deepAssign.js +39 -16
  181. package/tools/deepAssign.js.map +1 -1
  182. package/tools/formatNumber.js.map +1 -1
  183. package/tools/structuredCloneButFunctions.d.ts +7 -0
  184. package/tools/structuredCloneButFunctions.js +19 -0
  185. package/tools/structuredCloneButFunctions.js.map +1 -0
  186. package/tools/useInsertLinkTags.d.ts +11 -6
  187. package/tools/useInsertLinkTags.js +53 -53
  188. package/tools/useInsertLinkTags.js.map +1 -1
  189. package/tools/useInsertScriptTags.d.ts +15 -6
  190. package/tools/useInsertScriptTags.js +56 -64
  191. package/tools/useInsertScriptTags.js.map +1 -1
  192. package/tools/useOnFirstMount.d.ts +2 -0
  193. package/tools/useOnFirstMount.js +15 -0
  194. package/tools/useOnFirstMount.js.map +1 -0
  195. package/tools/useSetClassName.js.map +1 -1
  196. package/vite-plugin/index.js +66 -64
  197. package/account/kcContext/createGetKcContext.d.ts +0 -19
  198. package/account/kcContext/createGetKcContext.js +0 -78
  199. package/account/kcContext/createGetKcContext.js.map +0 -1
  200. package/account/kcContext/getKcContext.d.ts +0 -13
  201. package/account/kcContext/getKcContext.js +0 -13
  202. package/account/kcContext/getKcContext.js.map +0 -1
  203. package/account/kcContext/getKcContextFromWindow.d.ts +0 -10
  204. package/account/kcContext/getKcContextFromWindow.js +0 -5
  205. package/account/kcContext/getKcContextFromWindow.js.map +0 -1
  206. package/login/kcContext/createGetKcContext.d.ts +0 -19
  207. package/login/kcContext/createGetKcContext.js +0 -114
  208. package/login/kcContext/createGetKcContext.js.map +0 -1
  209. package/login/kcContext/getKcContext.d.ts +0 -13
  210. package/login/kcContext/getKcContext.js +0 -13
  211. package/login/kcContext/getKcContext.js.map +0 -1
  212. package/login/kcContext/getKcContextFromWindow.d.ts +0 -10
  213. package/login/kcContext/getKcContextFromWindow.js +0 -5
  214. package/login/kcContext/getKcContextFromWindow.js.map +0 -1
  215. package/src/account/kcContext/createGetKcContext.ts +0 -134
  216. package/src/account/kcContext/getKcContext.ts +0 -23
  217. package/src/account/kcContext/getKcContextFromWindow.ts +0 -15
  218. package/src/login/kcContext/createGetKcContext.ts +0 -199
  219. package/src/login/kcContext/getKcContext.ts +0 -23
  220. package/src/login/kcContext/getKcContextFromWindow.ts +0 -15
  221. package/src/tools/AndByDiscriminatingKey.ts +0 -31
  222. package/src/tools/deepClone.ts +0 -19
  223. package/src/tools/memoize.ts +0 -55
  224. package/tools/AndByDiscriminatingKey.d.ts +0 -5
  225. package/tools/AndByDiscriminatingKey.js +0 -2
  226. package/tools/AndByDiscriminatingKey.js.map +0 -1
  227. package/tools/deepClone.d.ts +0 -2
  228. package/tools/deepClone.js +0 -14
  229. package/tools/deepClone.js.map +0 -1
  230. package/tools/memoize.d.ts +0 -7
  231. package/tools/memoize.js +0 -38
  232. package/tools/memoize.js.map +0 -1
@@ -1,6 +1,12 @@
1
1
  import { useEffect, useReducer, Fragment } from "react";
2
2
  import type { ClassKey } from "keycloakify/login/TemplateProps";
3
- import { useUserProfileForm, type KcContextLike, type FormAction, type FormFieldError } from "keycloakify/login/lib/useUserProfileForm";
3
+ import {
4
+ useUserProfileForm,
5
+ getButtonToDisplayForMultivaluedAttributeField,
6
+ type KcContextLike,
7
+ type FormAction,
8
+ type FormFieldError
9
+ } from "keycloakify/login/lib/useUserProfileForm";
4
10
  import type { Attribute } from "keycloakify/login/kcContext/KcContext";
5
11
  import { assert } from "tsafe/assert";
6
12
  import type { I18n } from "./i18n";
@@ -413,92 +419,34 @@ function AddRemoveButtonsMultiValuedAttribute(props: {
413
419
 
414
420
  const { msg } = i18n;
415
421
 
416
- const hasRemove = (() => {
417
- if (values.length === 1) {
418
- return false;
419
- }
420
-
421
- const minCount = (() => {
422
- const { multivalued } = attribute.validators;
423
-
424
- if (multivalued === undefined) {
425
- return undefined;
426
- }
427
-
428
- const minStr = multivalued.min;
429
-
430
- if (minStr === undefined) {
431
- return undefined;
432
- }
433
-
434
- return parseInt(`${minStr}`);
435
- })();
436
-
437
- if (minCount === undefined) {
438
- return true;
439
- }
440
-
441
- if (values.length === minCount) {
442
- return false;
443
- }
444
-
445
- return true;
446
- })();
447
-
448
- const hasAdd = (() => {
449
- if (fieldIndex + 1 !== values.length) {
450
- return false;
451
- }
452
-
453
- const maxCount = (() => {
454
- const { multivalued } = attribute.validators;
455
-
456
- if (multivalued === undefined) {
457
- return undefined;
458
- }
459
-
460
- const maxStr = multivalued.max;
461
-
462
- if (maxStr === undefined) {
463
- return undefined;
464
- }
422
+ const { hasAdd, hasRemove } = getButtonToDisplayForMultivaluedAttributeField({ attribute, values, fieldIndex });
465
423
 
466
- return parseInt(`${maxStr}`);
467
- })();
468
-
469
- if (maxCount === undefined) {
470
- return false;
471
- }
472
-
473
- if (values.length === maxCount) {
474
- return false;
475
- }
476
-
477
- return true;
478
- })();
424
+ const idPostfix = `-${attribute.name}-${fieldIndex + 1}`;
479
425
 
480
426
  return (
481
427
  <>
482
428
  {hasRemove && (
483
- <button
484
- id={`kc-remove-${attribute.name}-${fieldIndex + 1}`}
485
- type="button"
486
- className="pf-c-button pf-m-inline pf-m-link"
487
- onClick={() =>
488
- dispatchFormAction({
489
- action: "update",
490
- name: attribute.name,
491
- valueOrValues: values.filter((_, i) => i !== fieldIndex)
492
- })
493
- }
494
- >
495
- {msg("remove")}
496
- {hasRemove ? <>&nbsp;|&nbsp;</> : null}
497
- </button>
429
+ <>
430
+ <button
431
+ id={`kc-remove${idPostfix}`}
432
+ type="button"
433
+ className="pf-c-button pf-m-inline pf-m-link"
434
+ onClick={() =>
435
+ dispatchFormAction({
436
+ action: "update",
437
+ name: attribute.name,
438
+ valueOrValues: values.filter((_, i) => i !== fieldIndex)
439
+ })
440
+ }
441
+ >
442
+ {msg("remove")}
443
+ </button>
444
+ {hasAdd ? <>&nbsp;|&nbsp;</> : null}
445
+ </>
498
446
  )}
499
447
  {hasAdd && (
500
448
  <button
501
- id="kc-add-titles-1"
449
+ id={`kc-add${idPostfix}`}
502
450
  type="button"
503
451
  className="pf-c-button pf-m-inline pf-m-link"
504
452
  onClick={() =>
@@ -580,7 +528,7 @@ function InputTagSelects(props: InputFiledByTypeProps) {
580
528
  className={classInput}
581
529
  aria-invalid={props.displayableErrors.length !== 0}
582
530
  disabled={attribute.readOnly}
583
- checked={valueOrValues.includes(option)}
531
+ checked={valueOrValues instanceof Array ? valueOrValues.includes(option) : valueOrValues === option}
584
532
  onChange={event =>
585
533
  formValidationDispatch({
586
534
  action: "update",
@@ -3,9 +3,12 @@ import Fallback from "keycloakify/login/Fallback";
3
3
  export default Fallback;
4
4
 
5
5
  export { useDownloadTerms } from "keycloakify/login/lib/useDownloadTerms";
6
- export { getKcContext } from "keycloakify/login/kcContext/getKcContext";
7
- export { createGetKcContext } from "keycloakify/login/kcContext/createGetKcContext";
8
- export type { LoginThemePageId as PageId } from "keycloakify/bin/shared/constants";
9
6
  export { createUseI18n } from "keycloakify/login/i18n/i18n";
7
+ export type {
8
+ ExtendKcContext,
9
+ Attribute,
10
+ PasswordPolicies
11
+ } from "keycloakify/login/kcContext";
12
+ export { createGetKcContextMock } from "keycloakify/login/kcContext";
10
13
 
11
14
  export type { PageProps } from "keycloakify/login/pages/PageProps";
@@ -3,14 +3,28 @@ import type {
3
3
  LoginThemePageId,
4
4
  nameOfTheLocalizationRealmOverridesUserProfileProperty
5
5
  } from "keycloakify/bin/shared/constants";
6
+ import type { ExtractAfterStartingWith } from "keycloakify/tools/ExtractAfterStartingWith";
7
+ import type { ValueOf } from "keycloakify/tools/ValueOf";
6
8
  import { assert } from "tsafe/assert";
7
9
  import type { Equals } from "tsafe";
8
10
  import type { MessageKey } from "../i18n/i18n";
9
11
 
10
- type ExtractAfterStartingWith<
11
- Prefix extends string,
12
- StrEnum
13
- > = StrEnum extends `${Prefix}${infer U}` ? U : never;
12
+ export type ExtendKcContext<
13
+ KcContextExtraProperties extends { properties?: Record<string, string | undefined> },
14
+ KcContextExtraPropertiesPerPage extends Record<string, Record<string, unknown>>
15
+ > = ValueOf<{
16
+ [PageId in keyof KcContextExtraPropertiesPerPage | KcContext["pageId"]]: Extract<
17
+ KcContext,
18
+ { pageId: PageId }
19
+ > extends never
20
+ ? KcContext.Common &
21
+ KcContextExtraProperties & {
22
+ pageId: PageId;
23
+ } & KcContextExtraPropertiesPerPage[PageId]
24
+ : Extract<KcContext, { pageId: PageId }> &
25
+ KcContextExtraProperties &
26
+ KcContextExtraPropertiesPerPage[PageId];
27
+ }>;
14
28
 
15
29
  /** Take theses type definition with a grain of salt.
16
30
  * Some values might be undefined on some pages.
@@ -138,12 +152,12 @@ export declare namespace KcContext {
138
152
 
139
153
  getFirstError: (...fieldNames: string[]) => string;
140
154
  };
141
- properties: Record<string, string | undefined>;
142
155
  authenticationSession?: {
143
156
  authSessionId: string;
144
157
  tabId: string;
145
158
  ssoLoginInOtherTabsUrl: string;
146
159
  };
160
+ properties: {};
147
161
  __localizationRealmOverridesUserProfile?: Record<string, string>;
148
162
  };
149
163
 
@@ -585,7 +599,7 @@ export declare namespace KcContext {
585
599
  }
586
600
 
587
601
  export type UserProfile = {
588
- attributes: Attribute[];
602
+ attributesByName: Record<string, Attribute>;
589
603
  html5DataAnnotations?: Record<string, string>;
590
604
  };
591
605
 
@@ -683,31 +697,31 @@ export type Attribute = {
683
697
  | "photo";
684
698
  };
685
699
 
686
- export type Validators = Partial<{
687
- length: Validators.DoIgnoreEmpty & Validators.Range;
688
- integer: Validators.DoIgnoreEmpty & Validators.Range;
689
- email: Validators.DoIgnoreEmpty;
690
- pattern: Validators.DoIgnoreEmpty & Validators.ErrorMessage & { pattern: string };
691
- options: Validators.Options;
692
- multivalued: Validators.DoIgnoreEmpty & Validators.Range;
700
+ export type Validators = {
701
+ length?: Validators.DoIgnoreEmpty & Validators.Range;
702
+ integer?: Validators.DoIgnoreEmpty & Validators.Range;
703
+ email?: Validators.DoIgnoreEmpty;
704
+ pattern?: Validators.DoIgnoreEmpty & Validators.ErrorMessage & { pattern: string };
705
+ options?: Validators.Options;
706
+ multivalued?: Validators.DoIgnoreEmpty & Validators.Range;
693
707
  // NOTE: Following are the validators for which we don't implement client side validation yet
694
708
  // or for which the validation can't be performed on the client side.
695
709
  /*
696
- double: Validators.DoIgnoreEmpty & Validators.Range;
697
- "up-immutable-attribute": {};
698
- "up-attribute-required-by-metadata-value": {};
699
- "up-username-has-value": {};
700
- "up-duplicate-username": {};
701
- "up-username-mutation": {};
702
- "up-email-exists-as-username": {};
703
- "up-blank-attribute-value": Validators.ErrorMessage & { "fail-on-null": boolean; };
704
- "up-duplicate-email": {};
705
- "local-date": Validators.DoIgnoreEmpty;
706
- "person-name-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
707
- uri: Validators.DoIgnoreEmpty;
708
- "username-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
710
+ double?: Validators.DoIgnoreEmpty & Validators.Range;
711
+ "up-immutable-attribute"?: {};
712
+ "up-attribute-required-by-metadata-value"?: {};
713
+ "up-username-has-value"?: {};
714
+ "up-duplicate-username"?: {};
715
+ "up-username-mutation"?: {};
716
+ "up-email-exists-as-username"?: {};
717
+ "up-blank-attribute-value"?: Validators.ErrorMessage & { "fail-on-null": boolean; };
718
+ "up-duplicate-email"?: {};
719
+ "local-date"?: Validators.DoIgnoreEmpty;
720
+ "person-name-prohibited-characters"?: Validators.DoIgnoreEmpty & Validators.ErrorMessage;
721
+ uri?: Validators.DoIgnoreEmpty;
722
+ "username-prohibited-characters"?: Validators.DoIgnoreEmpty & Validators.ErrorMessage;
709
723
  */
710
- }>;
724
+ };
711
725
 
712
726
  export declare namespace Validators {
713
727
  export type DoIgnoreEmpty = {
@@ -0,0 +1,80 @@
1
+ import type { ExtendKcContext, KcContext as KcContextBase } from "./KcContext";
2
+ import type { LoginThemePageId } from "keycloakify/bin/shared/constants";
3
+ import type { DeepPartial } from "keycloakify/tools/DeepPartial";
4
+ import { deepAssign } from "keycloakify/tools/deepAssign";
5
+ import { structuredCloneButFunctions } from "keycloakify/tools/structuredCloneButFunctions";
6
+ import { kcContextMocks, kcContextCommonMock } from "./kcContextMocks";
7
+ import { exclude } from "tsafe/exclude";
8
+
9
+ export function createGetKcContextMock<
10
+ KcContextExtraProperties extends { properties?: Record<string, string | undefined> },
11
+ KcContextExtraPropertiesPerPage extends Record<
12
+ `${string}.ftl`,
13
+ Record<string, unknown>
14
+ >
15
+ >(params: {
16
+ kcContextExtraProperties: KcContextExtraProperties;
17
+ kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage;
18
+ overrides?: DeepPartial<KcContextExtraProperties & KcContextBase.Common>;
19
+ overridesPerPage?: {
20
+ [PageId in
21
+ | LoginThemePageId
22
+ | keyof KcContextExtraPropertiesPerPage]?: DeepPartial<
23
+ Extract<
24
+ ExtendKcContext<
25
+ KcContextExtraProperties,
26
+ KcContextExtraPropertiesPerPage
27
+ >,
28
+ { pageId: PageId }
29
+ >
30
+ >;
31
+ };
32
+ }) {
33
+ const {
34
+ kcContextExtraProperties,
35
+ kcContextExtraPropertiesPerPage,
36
+ overrides: overrides_global,
37
+ overridesPerPage: overridesPerPage_global
38
+ } = params;
39
+
40
+ type KcContext = ExtendKcContext<
41
+ KcContextExtraProperties,
42
+ KcContextExtraPropertiesPerPage
43
+ >;
44
+
45
+ function getKcContextMock<
46
+ PageId extends LoginThemePageId | keyof KcContextExtraPropertiesPerPage
47
+ >(params: {
48
+ pageId: PageId;
49
+ overrides?: DeepPartial<Extract<KcContext, { pageId: PageId }>>;
50
+ }): Extract<KcContext, { pageId: PageId }> {
51
+ const { pageId, overrides } = params;
52
+
53
+ const kcContextMock = structuredCloneButFunctions(
54
+ kcContextMocks.find(kcContextMock => kcContextMock.pageId === pageId) ?? {
55
+ ...kcContextCommonMock,
56
+ pageId
57
+ }
58
+ );
59
+
60
+ [
61
+ kcContextExtraProperties,
62
+ kcContextExtraPropertiesPerPage[pageId],
63
+ overrides_global,
64
+ overridesPerPage_global?.[pageId],
65
+ overrides
66
+ ]
67
+ .filter(exclude(undefined))
68
+ .forEach(overrides =>
69
+ deepAssign({
70
+ target: kcContextMock,
71
+ source: overrides
72
+ })
73
+ );
74
+
75
+ // @ts-expect-error
76
+ return kcContextMock;
77
+ }
78
+
79
+ return { getKcContextMock };
80
+ }
@@ -1 +1,7 @@
1
- export type { KcContext } from "./KcContext";
1
+ export type {
2
+ ExtendKcContext,
3
+ KcContext,
4
+ Attribute,
5
+ PasswordPolicies
6
+ } from "./KcContext";
7
+ export { createGetKcContextMock } from "./getKcContextMock";
@@ -9,71 +9,72 @@ import { id } from "tsafe/id";
9
9
  import { assert, type Equals } from "tsafe/assert";
10
10
  import { BASE_URL } from "keycloakify/lib/BASE_URL";
11
11
 
12
- const attributes: Attribute[] = [
13
- {
14
- validators: {
15
- length: {
16
- "ignore.empty.value": true,
17
- min: "3",
18
- max: "255"
19
- }
20
- },
21
- displayName: "${username}",
22
- annotations: {},
23
- required: true,
24
- autocomplete: "username",
25
- readOnly: false,
26
- name: "username",
27
- value: "xxxx"
28
- },
29
- {
30
- validators: {
31
- length: {
32
- max: "255",
33
- "ignore.empty.value": true
34
- },
35
- email: {
36
- "ignore.empty.value": true
12
+ const attributesByName = Object.fromEntries(
13
+ id<Attribute[]>([
14
+ {
15
+ validators: {
16
+ length: {
17
+ "ignore.empty.value": true,
18
+ min: "3",
19
+ max: "255"
20
+ }
37
21
  },
38
- pattern: {
39
- "ignore.empty.value": true,
40
- pattern: "gmail\\.com$"
41
- }
22
+ displayName: "${username}",
23
+ annotations: {},
24
+ required: true,
25
+ autocomplete: "username",
26
+ readOnly: false,
27
+ name: "username"
42
28
  },
43
- displayName: "${email}",
44
- annotations: {},
45
- required: true,
46
- autocomplete: "email",
47
- readOnly: false,
48
- name: "email"
49
- },
50
- {
51
- validators: {
52
- length: {
53
- max: "255",
54
- "ignore.empty.value": true
55
- }
29
+ {
30
+ validators: {
31
+ length: {
32
+ max: "255",
33
+ "ignore.empty.value": true
34
+ },
35
+ email: {
36
+ "ignore.empty.value": true
37
+ },
38
+ pattern: {
39
+ "ignore.empty.value": true,
40
+ pattern: "gmail\\.com$"
41
+ }
42
+ },
43
+ displayName: "${email}",
44
+ annotations: {},
45
+ required: true,
46
+ autocomplete: "email",
47
+ readOnly: false,
48
+ name: "email"
56
49
  },
57
- displayName: "${firstName}",
58
- annotations: {},
59
- required: true,
60
- readOnly: false,
61
- name: "firstName"
62
- },
63
- {
64
- validators: {
65
- length: {
66
- max: "255",
67
- "ignore.empty.value": true
68
- }
50
+ {
51
+ validators: {
52
+ length: {
53
+ max: "255",
54
+ "ignore.empty.value": true
55
+ }
56
+ },
57
+ displayName: "${firstName}",
58
+ annotations: {},
59
+ required: true,
60
+ readOnly: false,
61
+ name: "firstName"
69
62
  },
70
- displayName: "${lastName}",
71
- annotations: {},
72
- required: true,
73
- readOnly: false,
74
- name: "lastName"
75
- }
76
- ];
63
+ {
64
+ validators: {
65
+ length: {
66
+ max: "255",
67
+ "ignore.empty.value": true
68
+ }
69
+ },
70
+ displayName: "${lastName}",
71
+ annotations: {},
72
+ required: true,
73
+ readOnly: false,
74
+ name: "lastName"
75
+ }
76
+ ]).map(attribute => [attribute.name, attribute])
77
+ );
77
78
 
78
79
  const resourcesPath = `${BASE_URL}${keycloak_resources}/login/resources`;
79
80
 
@@ -112,98 +113,34 @@ export const kcContextCommonMock: KcContext.Common = {
112
113
  locale: {
113
114
  supported: [
114
115
  /* spell-checker: disable */
115
- {
116
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=de",
117
- label: "Deutsch",
118
- languageTag: "de"
119
- },
120
- {
121
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=no",
122
- label: "Norsk",
123
- languageTag: "no"
124
- },
125
- {
126
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=ru",
127
- label: "Русский",
128
- languageTag: "ru"
129
- },
130
- {
131
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=sv",
132
- label: "Svenska",
133
- languageTag: "sv"
134
- },
135
- {
136
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=pt-BR",
137
- label: "Português (Brasil)",
138
- languageTag: "pt-BR"
139
- },
140
- {
141
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=lt",
142
- label: "Lietuvių",
143
- languageTag: "lt"
144
- },
145
- {
146
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=en",
147
- label: "English",
148
- languageTag: "en"
149
- },
150
- {
151
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=it",
152
- label: "Italiano",
153
- languageTag: "it"
154
- },
155
- {
156
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=fr",
157
- label: "Français",
158
- languageTag: "fr"
159
- },
160
- {
161
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=zh-CN",
162
- label: "中文简体",
163
- languageTag: "zh-CN"
164
- },
165
- {
166
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=es",
167
- label: "Español",
168
- languageTag: "es"
169
- },
170
- {
171
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=cs",
172
- label: "Čeština",
173
- languageTag: "cs"
174
- },
175
- {
176
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=ja",
177
- label: "日本語",
178
- languageTag: "ja"
179
- },
180
- {
181
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=sk",
182
- label: "Slovenčina",
183
- languageTag: "sk"
184
- },
185
- {
186
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=pl",
187
- label: "Polski",
188
- languageTag: "pl"
189
- },
190
- {
191
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=ca",
192
- label: "Català",
193
- languageTag: "ca"
194
- },
195
- {
196
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=nl",
197
- label: "Nederlands",
198
- languageTag: "nl"
199
- },
200
- {
201
- url: "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=tr",
202
- label: "Türkçe",
203
- languageTag: "tr"
204
- }
116
+ ["de", "Deutsch"],
117
+ ["no", "Norsk"],
118
+ ["ru", "Русский"],
119
+ ["sv", "Svenska"],
120
+ ["pt-BR", "Português (Brasil)"],
121
+ ["lt", "Lietuvių"],
122
+ ["en", "English"],
123
+ ["it", "Italiano"],
124
+ ["fr", "Français"],
125
+ ["zh-CN", "中文简体"],
126
+ ["es", "Español"],
127
+ ["cs", "Čeština"],
128
+ ["ja", "日本語"],
129
+ ["sk", "Slovenčina"],
130
+ ["pl", "Polski"],
131
+ ["ca", "Català"],
132
+ ["nl", "Nederlands"],
133
+ ["tr", "Türkçe"]
205
134
  /* spell-checker: enable */
206
- ],
135
+ ].map(
136
+ ([languageTag, label]) =>
137
+ ({
138
+ languageTag,
139
+ label,
140
+ url: "https://gist.github.com/garronej/52baaca1bb925f2296ab32741e062b8e"
141
+ }) as const
142
+ ),
143
+
207
144
  currentLanguageTag: "en"
208
145
  },
209
146
  auth: {
@@ -265,7 +202,7 @@ export const kcContextMocks = [
265
202
  recaptchaRequired: false,
266
203
  pageId: "register.ftl",
267
204
  profile: {
268
- attributes
205
+ attributesByName
269
206
  },
270
207
  scripts: [
271
208
  //"https://www.google.com/recaptcha/api.js"
@@ -416,7 +353,7 @@ export const kcContextMocks = [
416
353
  ...kcContextCommonMock,
417
354
  pageId: "login-update-profile.ftl",
418
355
  profile: {
419
- attributes
356
+ attributesByName
420
357
  }
421
358
  }),
422
359
  id<KcContext.LoginIdpLinkConfirm>({
@@ -472,14 +409,16 @@ export const kcContextMocks = [
472
409
  ...kcContextCommonMock,
473
410
  pageId: "idp-review-user-profile.ftl",
474
411
  profile: {
475
- attributes
412
+ attributesByName
476
413
  }
477
414
  }),
478
415
  id<KcContext.UpdateEmail>({
479
416
  ...kcContextCommonMock,
480
417
  pageId: "update-email.ftl",
481
418
  profile: {
482
- attributes: attributes.filter(attribute => attribute.name === "email")
419
+ attributesByName: {
420
+ email: attributesByName["email"]
421
+ }
483
422
  }
484
423
  }),
485
424
  id<KcContext.SelectAuthenticator>({