keycloakify 10.0.0-rc.38 → 10.0.0-rc.39

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 (81) hide show
  1. package/bin/193.index.js +13 -13
  2. package/bin/3.index.js +86 -86
  3. package/bin/322.index.js +595 -0
  4. package/bin/453.index.js +3 -3
  5. package/bin/526.index.js +42 -633
  6. package/bin/538.index.js +68 -57
  7. package/bin/932.index.js +7 -7
  8. package/bin/944.index.js +621 -0
  9. package/bin/961.index.js +5 -5
  10. package/bin/97.index.js +3 -3
  11. package/bin/{21.index.js → 98.index.js} +59 -48
  12. package/bin/main.js +8 -8
  13. package/lib/getKcClsx.js +12 -1
  14. package/lib/getKcClsx.js.map +1 -1
  15. package/login/Fallback.d.ts +1 -0
  16. package/login/Fallback.js.map +1 -1
  17. package/login/UserProfileFormFields.d.ts +1 -0
  18. package/login/UserProfileFormFields.js +1 -3
  19. package/login/UserProfileFormFields.js.map +1 -1
  20. package/login/i18n/i18n.js +1 -1
  21. package/login/pages/IdpReviewUserProfile.d.ts +1 -0
  22. package/login/pages/IdpReviewUserProfile.js +2 -2
  23. package/login/pages/IdpReviewUserProfile.js.map +1 -1
  24. package/login/pages/LoginUpdateProfile.d.ts +1 -0
  25. package/login/pages/LoginUpdateProfile.js +2 -2
  26. package/login/pages/LoginUpdateProfile.js.map +1 -1
  27. package/login/pages/Register.d.ts +1 -0
  28. package/login/pages/Register.js +2 -2
  29. package/login/pages/Register.js.map +1 -1
  30. package/login/pages/UpdateEmail.d.ts +1 -0
  31. package/login/pages/UpdateEmail.js +2 -2
  32. package/login/pages/UpdateEmail.js.map +1 -1
  33. package/package.json +5 -8
  34. package/src/bin/add-story.ts +3 -3
  35. package/src/bin/copy-keycloak-resources-to-public.ts +3 -3
  36. package/src/bin/download-keycloak-default-theme.ts +5 -5
  37. package/src/bin/eject-page.ts +3 -3
  38. package/src/bin/initialize-email-theme.ts +5 -5
  39. package/src/bin/keycloakify/buildJars/buildJar.ts +14 -14
  40. package/src/bin/keycloakify/buildJars/buildJars.ts +8 -8
  41. package/src/bin/keycloakify/buildJars/generatePom.ts +9 -9
  42. package/src/bin/keycloakify/generateFtl/generateFtl.ts +12 -12
  43. package/src/bin/keycloakify/generateSrcMainResources/bringInAccountV1.ts +7 -7
  44. package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResources.ts +9 -9
  45. package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForMainTheme.ts +25 -25
  46. package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForThemeVariant.ts +8 -8
  47. package/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts +9 -9
  48. package/src/bin/keycloakify/keycloakify.ts +11 -11
  49. package/src/bin/keycloakify/replacers/replaceImportsInCssCode.ts +6 -6
  50. package/src/bin/keycloakify/replacers/replaceImportsInInlineCssCode.ts +7 -7
  51. package/src/bin/keycloakify/replacers/replaceImportsInJsCode/replaceImportsInJsCode.ts +10 -10
  52. package/src/bin/keycloakify/replacers/replaceImportsInJsCode/vite.ts +13 -13
  53. package/src/bin/keycloakify/replacers/replaceImportsInJsCode/webpack.ts +11 -11
  54. package/src/bin/main.ts +2 -2
  55. package/src/bin/shared/{buildOptions.ts → buildContext.ts} +62 -51
  56. package/src/bin/shared/copyKeycloakResourcesToPublic.ts +12 -12
  57. package/src/bin/shared/downloadKeycloakDefaultTheme.ts +7 -7
  58. package/src/bin/shared/downloadKeycloakStaticResources.ts +7 -7
  59. package/src/bin/shared/generateKcGenTs.ts +12 -12
  60. package/src/bin/shared/getThemeSrcDirPath.ts +3 -3
  61. package/src/bin/start-keycloak/appBuild.ts +11 -11
  62. package/src/bin/start-keycloak/keycloakifyBuild.ts +7 -7
  63. package/src/bin/start-keycloak/start-keycloak.ts +34 -22
  64. package/src/bin/tools/getNpmWorkspaceRootDirPath.ts +3 -3
  65. package/src/bin/update-kc-gen.ts +3 -3
  66. package/src/lib/getKcClsx.ts +15 -1
  67. package/src/login/Fallback.tsx +1 -0
  68. package/src/login/UserProfileFormFields.tsx +2 -4
  69. package/src/login/i18n/i18n.tsx +1 -1
  70. package/src/login/pages/IdpReviewUserProfile.tsx +8 -2
  71. package/src/login/pages/LoginUpdateProfile.tsx +8 -2
  72. package/src/login/pages/Register.tsx +8 -2
  73. package/src/login/pages/UpdateEmail.tsx +8 -2
  74. package/src/vite-plugin/vite-plugin.ts +19 -19
  75. package/vite-plugin/index.js +91 -80
  76. package/vite-plugin/vite-plugin.d.ts +3 -3
  77. package/bin/795.index.js +0 -1198
  78. package/lib/isStorybook.d.ts +0 -1
  79. package/lib/isStorybook.js +0 -3
  80. package/lib/isStorybook.js.map +0 -1
  81. package/src/lib/isStorybook.ts +0 -3
@@ -1,4 +1,5 @@
1
- import { readBuildOptions } from "../shared/buildOptions";
1
+ import { getBuildContext } from "../shared/buildContext";
2
+ import { exclude } from "tsafe/exclude";
2
3
  import type { CliCommandOptions as CliCommandOptions_common } from "../main";
3
4
  import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
4
5
  import { readMetaInfKeycloakThemes } from "../shared/metaInfKeycloakThemes";
@@ -80,11 +81,11 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
80
81
 
81
82
  const { cliCommandOptions } = params;
82
83
 
83
- const buildOptions = readBuildOptions({ cliCommandOptions });
84
+ const buildContext = getBuildContext({ cliCommandOptions });
84
85
 
85
86
  {
86
87
  const { isAppBuildSuccess } = await appBuild({
87
- buildOptions
88
+ buildContext
88
89
  });
89
90
 
90
91
  if (!isAppBuildSuccess) {
@@ -98,7 +99,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
98
99
 
99
100
  const { isKeycloakifyBuildSuccess } = await keycloakifyBuild({
100
101
  doSkipBuildJars: false,
101
- buildOptions
102
+ buildContext
102
103
  });
103
104
 
104
105
  if (!isKeycloakifyBuildSuccess) {
@@ -112,7 +113,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
112
113
  }
113
114
 
114
115
  const metaInfKeycloakThemes = readMetaInfKeycloakThemes({
115
- keycloakifyBuildDirPath: buildOptions.keycloakifyBuildDirPath
116
+ keycloakifyBuildDirPath: buildContext.keycloakifyBuildDirPath
116
117
  });
117
118
 
118
119
  const doesImplementAccountTheme = metaInfKeycloakThemes.themes.some(
@@ -138,7 +139,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
138
139
 
139
140
  const { keycloakVersion } = await promptKeycloakVersion({
140
141
  startingFromMajor: 17,
141
- cacheDirPath: buildOptions.cacheDirPath
142
+ cacheDirPath: buildContext.cacheDirPath
142
143
  });
143
144
 
144
145
  console.log(`→ ${keycloakVersion}`);
@@ -259,7 +260,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
259
260
  return pathJoin(dirPath, value);
260
261
  })();
261
262
 
262
- const jarFilePath = pathJoin(buildOptions.keycloakifyBuildDirPath, jarFileBasename);
263
+ const jarFilePath = pathJoin(buildContext.keycloakifyBuildDirPath, jarFileBasename);
263
264
 
264
265
  const { doUseBuiltInAccountV1Theme } = await (async () => {
265
266
  let doUseBuiltInAccountV1Theme = false;
@@ -267,7 +268,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
267
268
  await extractArchive({
268
269
  archiveFilePath: jarFilePath,
269
270
  onArchiveFile: async ({ relativeFilePathInArchive, readFile, earlyExit }) => {
270
- for (const themeName of buildOptions.themeNames) {
271
+ for (const themeName of buildContext.themeNames) {
271
272
  if (
272
273
  relativeFilePathInArchive ===
273
274
  pathJoin("theme", themeName, "account", "theme.properties")
@@ -292,9 +293,9 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
292
293
  const accountThemePropertyPatch = !doUseBuiltInAccountV1Theme
293
294
  ? undefined
294
295
  : () => {
295
- for (const themeName of buildOptions.themeNames) {
296
+ for (const themeName of buildContext.themeNames) {
296
297
  const filePath = pathJoin(
297
- buildOptions.keycloakifyBuildDirPath,
298
+ buildContext.keycloakifyBuildDirPath,
298
299
  "src",
299
300
  "main",
300
301
  "resources",
@@ -346,12 +347,12 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
346
347
  ? ["-e", "JAVA_OPTS=-Dkeycloak.profile=preview"]
347
348
  : []),
348
349
  ...[
349
- ...buildOptions.themeNames,
350
+ ...buildContext.themeNames,
350
351
  ...(doUseBuiltInAccountV1Theme ? [] : [accountV1ThemeName])
351
352
  ]
352
353
  .map(themeName => ({
353
354
  localDirPath: pathJoin(
354
- buildOptions.keycloakifyBuildDirPath,
355
+ buildContext.keycloakifyBuildDirPath,
355
356
  "src",
356
357
  "main",
357
358
  "resources",
@@ -365,6 +366,17 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
365
366
  `${localDirPath}:${containerDirPath}:rw`
366
367
  ])
367
368
  .flat(),
369
+ ...buildContext.environmentVariables
370
+ .map(({ name }) => ({ name, envValue: process.env[name] }))
371
+ .map(({ name, envValue }) =>
372
+ envValue === undefined ? undefined : { name, envValue }
373
+ )
374
+ .filter(exclude(undefined))
375
+ .map(({ name, envValue }) => [
376
+ "--env",
377
+ `${name}='${envValue.replace(/'/g, "'\\''")}'`
378
+ ])
379
+ .flat(),
368
380
  `quay.io/keycloak/keycloak:${keycloakVersion}`,
369
381
  "start-dev",
370
382
  ...(21 <= keycloakMajorVersionNumber && keycloakMajorVersionNumber < 24
@@ -373,7 +385,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
373
385
  ...(realmJsonFilePath === undefined ? [] : ["--import-realm"])
374
386
  ],
375
387
  {
376
- cwd: buildOptions.keycloakifyBuildDirPath
388
+ cwd: buildContext.keycloakifyBuildDirPath
377
389
  }
378
390
  ] as const;
379
391
 
@@ -385,7 +397,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
385
397
 
386
398
  child.on("exit", process.exit);
387
399
 
388
- const srcDirPath = pathJoin(buildOptions.reactAppRootDirPath, "src");
400
+ const srcDirPath = pathJoin(buildContext.projectDirPath, "src");
389
401
 
390
402
  {
391
403
  const handler = async (data: Buffer) => {
@@ -417,7 +429,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
417
429
  `- password: ${chalk.cyan.bold("password123")}`,
418
430
  "",
419
431
  `Watching for changes in ${chalk.bold(
420
- `.${pathSep}${pathRelative(process.cwd(), buildOptions.reactAppRootDirPath)}`
432
+ `.${pathSep}${pathRelative(process.cwd(), buildContext.projectDirPath)}`
421
433
  )}`
422
434
  ].join("\n")
423
435
  );
@@ -431,7 +443,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
431
443
  console.log(chalk.cyan("Detected changes in the theme. Rebuilding ..."));
432
444
 
433
445
  const { isAppBuildSuccess } = await appBuild({
434
- buildOptions
446
+ buildContext
435
447
  });
436
448
 
437
449
  if (!isAppBuildSuccess) {
@@ -440,7 +452,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
440
452
 
441
453
  const { isKeycloakifyBuildSuccess } = await keycloakifyBuild({
442
454
  doSkipBuildJars: true,
443
- buildOptions
455
+ buildContext
444
456
  });
445
457
 
446
458
  if (!isKeycloakifyBuildSuccess) {
@@ -458,11 +470,11 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
458
470
  .watch(
459
471
  [
460
472
  srcDirPath,
461
- buildOptions.publicDirPath,
462
- pathJoin(buildOptions.reactAppRootDirPath, "package.json"),
463
- pathJoin(buildOptions.reactAppRootDirPath, "vite.config.ts"),
464
- pathJoin(buildOptions.reactAppRootDirPath, "vite.config.js"),
465
- pathJoin(buildOptions.reactAppRootDirPath, "index.html"),
473
+ buildContext.publicDirPath,
474
+ pathJoin(buildContext.projectDirPath, "package.json"),
475
+ pathJoin(buildContext.projectDirPath, "vite.config.ts"),
476
+ pathJoin(buildContext.projectDirPath, "vite.config.js"),
477
+ pathJoin(buildContext.projectDirPath, "index.html"),
466
478
  pathJoin(getThisCodebaseRootDirPath(), "src")
467
479
  ],
468
480
  {
@@ -4,14 +4,14 @@ import { assert } from "tsafe/assert";
4
4
  import * as fs from "fs";
5
5
 
6
6
  export function getNpmWorkspaceRootDirPath(params: {
7
- reactAppRootDirPath: string;
7
+ projectDirPath: string;
8
8
  dependencyExpected: string;
9
9
  }) {
10
- const { reactAppRootDirPath, dependencyExpected } = params;
10
+ const { projectDirPath, dependencyExpected } = params;
11
11
 
12
12
  const npmWorkspaceRootDirPath = (function callee(depth: number): string {
13
13
  const cwd = pathResolve(
14
- pathJoin(...[reactAppRootDirPath, ...Array(depth).fill("..")])
14
+ pathJoin(...[projectDirPath, ...Array(depth).fill("..")])
15
15
  );
16
16
 
17
17
  assert(cwd !== pathSep, "NPM workspace not found");
@@ -1,13 +1,13 @@
1
1
  import type { CliCommandOptions } from "./main";
2
- import { readBuildOptions } from "./shared/buildOptions";
2
+ import { getBuildContext } from "./shared/buildContext";
3
3
  import { generateKcGenTs } from "./shared/generateKcGenTs";
4
4
 
5
5
  export async function command(params: { cliCommandOptions: CliCommandOptions }) {
6
6
  const { cliCommandOptions } = params;
7
7
 
8
- const buildOptions = readBuildOptions({
8
+ const buildContext = getBuildContext({
9
9
  cliCommandOptions
10
10
  });
11
11
 
12
- await generateKcGenTs({ buildOptions });
12
+ await generateKcGenTs({ buildContext });
13
13
  }
@@ -21,7 +21,21 @@ export function createGetKcClsx<ClassKey extends string>(params: {
21
21
  return true;
22
22
  }
23
23
 
24
- return JSON.stringify(params1.classes) === JSON.stringify(params2.classes);
24
+ if (params1.classes === undefined || params2.classes === undefined) {
25
+ return false;
26
+ }
27
+
28
+ if (Object.keys(params1.classes).length !== Object.keys(params2.classes).length) {
29
+ return false;
30
+ }
31
+
32
+ for (const key in params1.classes) {
33
+ if (params1.classes[key] !== params2.classes[key]) {
34
+ return false;
35
+ }
36
+ }
37
+
38
+ return true;
25
39
  }
26
40
 
27
41
  let cache:
@@ -42,6 +42,7 @@ const WebauthnError = lazy(() => import("keycloakify/login/pages/WebauthnError")
42
42
 
43
43
  type FallbackProps = PageProps<KcContext> & {
44
44
  UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>;
45
+ doMakeUserConfirmPassword: boolean;
45
46
  };
46
47
 
47
48
  export default function Fallback(props: FallbackProps) {
@@ -15,6 +15,7 @@ export type UserProfileFormFieldsProps = {
15
15
  kcContext: KcContextLike;
16
16
  kcClsx: KcClsx;
17
17
  onIsFormSubmittableValueChange: (isFormSubmittable: boolean) => void;
18
+ doMakeUserConfirmPassword: boolean;
18
19
  BeforeField?: (props: BeforeAfterFieldProps) => JSX.Element | null;
19
20
  AfterField?: (props: BeforeAfterFieldProps) => JSX.Element | null;
20
21
  };
@@ -28,11 +29,8 @@ type BeforeAfterFieldProps = {
28
29
  i18n: I18n;
29
30
  };
30
31
 
31
- // NOTE: Enabled by default but it's a UX best practice to set it to false.
32
- const doMakeUserConfirmPassword = true;
33
-
34
32
  export default function UserProfileFormFields(props: UserProfileFormFieldsProps) {
35
- const { kcContext, kcClsx, onIsFormSubmittableValueChange, BeforeField, AfterField } = props;
33
+ const { kcContext, kcClsx, onIsFormSubmittableValueChange, doMakeUserConfirmPassword, BeforeField, AfterField } = props;
36
34
 
37
35
  const { advancedMsg } = useI18n({ kcContext });
38
36
 
@@ -132,7 +132,7 @@ function createGetI18n<ExtraMessageKey extends string = never>(extraMessages: {
132
132
  __localizationRealmOverridesUserProfile: kcContext.__localizationRealmOverridesUserProfile
133
133
  });
134
134
 
135
- const isCurrentLanguageFallbackLanguage = partialI18n.currentLanguageTag !== fallbackLanguageTag;
135
+ const isCurrentLanguageFallbackLanguage = partialI18n.currentLanguageTag === fallbackLanguageTag;
136
136
 
137
137
  const result: Result = {
138
138
  i18n: {
@@ -8,10 +8,11 @@ import { useI18n } from "../i18n";
8
8
 
9
9
  type IdpReviewUserProfileProps = PageProps<Extract<KcContext, { pageId: "idp-review-user-profile.ftl" }>> & {
10
10
  UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>;
11
+ doMakeUserConfirmPassword: boolean;
11
12
  };
12
13
 
13
14
  export default function IdpReviewUserProfile(props: IdpReviewUserProfileProps) {
14
- const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
15
+ const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields, doMakeUserConfirmPassword } = props;
15
16
 
16
17
  const { kcClsx } = getKcClsx({
17
18
  doUseDefaultCss,
@@ -34,7 +35,12 @@ export default function IdpReviewUserProfile(props: IdpReviewUserProfileProps) {
34
35
  headerNode={msg("loginIdpReviewProfileTitle")}
35
36
  >
36
37
  <form id="kc-idp-review-profile-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
37
- <UserProfileFormFields kcContext={kcContext} onIsFormSubmittableValueChange={setIsFomSubmittable} kcClsx={kcClsx} />
38
+ <UserProfileFormFields
39
+ kcContext={kcContext}
40
+ onIsFormSubmittableValueChange={setIsFomSubmittable}
41
+ kcClsx={kcClsx}
42
+ doMakeUserConfirmPassword={doMakeUserConfirmPassword}
43
+ />
38
44
  <div className={kcClsx("kcFormGroupClass")}>
39
45
  <div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
40
46
  <div className={kcClsx("kcFormOptionsWrapperClass")} />
@@ -8,10 +8,11 @@ import { useI18n } from "../i18n";
8
8
 
9
9
  type LoginUpdateProfileProps = PageProps<Extract<KcContext, { pageId: "login-update-profile.ftl" }>> & {
10
10
  UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>;
11
+ doMakeUserConfirmPassword: boolean;
11
12
  };
12
13
 
13
14
  export default function LoginUpdateProfile(props: LoginUpdateProfileProps) {
14
- const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
15
+ const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields, doMakeUserConfirmPassword } = props;
15
16
 
16
17
  const { kcClsx } = getKcClsx({
17
18
  doUseDefaultCss,
@@ -33,7 +34,12 @@ export default function LoginUpdateProfile(props: LoginUpdateProfileProps) {
33
34
  headerNode={msg("loginProfileTitle")}
34
35
  >
35
36
  <form id="kc-update-profile-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
36
- <UserProfileFormFields kcContext={kcContext} kcClsx={kcClsx} onIsFormSubmittableValueChange={setIsFormSubmittable} />
37
+ <UserProfileFormFields
38
+ kcContext={kcContext}
39
+ kcClsx={kcClsx}
40
+ onIsFormSubmittableValueChange={setIsFormSubmittable}
41
+ doMakeUserConfirmPassword={doMakeUserConfirmPassword}
42
+ />
37
43
  <div className={kcClsx("kcFormGroupClass")}>
38
44
  <div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
39
45
  <div className={kcClsx("kcFormOptionsWrapperClass")} />
@@ -10,10 +10,11 @@ import { useI18n, type I18n } from "../i18n";
10
10
 
11
11
  type RegisterProps = PageProps<Extract<KcContext, { pageId: "register.ftl" }>> & {
12
12
  UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>;
13
+ doMakeUserConfirmPassword: boolean;
13
14
  };
14
15
 
15
16
  export default function Register(props: RegisterProps) {
16
- const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
17
+ const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields, doMakeUserConfirmPassword } = props;
17
18
 
18
19
  const { kcClsx } = getKcClsx({
19
20
  doUseDefaultCss,
@@ -30,7 +31,12 @@ export default function Register(props: RegisterProps) {
30
31
  return (
31
32
  <Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("registerTitle")} displayRequiredFields>
32
33
  <form id="kc-register-form" className={kcClsx("kcFormClass")} action={url.registrationAction} method="post">
33
- <UserProfileFormFields kcContext={kcContext} kcClsx={kcClsx} onIsFormSubmittableValueChange={setIsFormSubmittable} />
34
+ <UserProfileFormFields
35
+ kcContext={kcContext}
36
+ kcClsx={kcClsx}
37
+ onIsFormSubmittableValueChange={setIsFormSubmittable}
38
+ doMakeUserConfirmPassword={doMakeUserConfirmPassword}
39
+ />
34
40
  {termsAcceptanceRequired && <TermsAcceptance i18n={i18n} kcClsx={kcClsx} messagesPerField={messagesPerField} />}
35
41
  {recaptchaRequired && (
36
42
  <div className="form-group">
@@ -8,10 +8,11 @@ import { useI18n, type I18n } from "../i18n";
8
8
 
9
9
  type UpdateEmailProps = PageProps<Extract<KcContext, { pageId: "update-email.ftl" }>> & {
10
10
  UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>;
11
+ doMakeUserConfirmPassword: boolean;
11
12
  };
12
13
 
13
14
  export default function UpdateEmail(props: UpdateEmailProps) {
14
- const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
15
+ const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields, doMakeUserConfirmPassword } = props;
15
16
 
16
17
  const { kcClsx } = getKcClsx({
17
18
  doUseDefaultCss,
@@ -35,7 +36,12 @@ export default function UpdateEmail(props: UpdateEmailProps) {
35
36
  headerNode={msg("updateEmailTitle")}
36
37
  >
37
38
  <form id="kc-update-email-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
38
- <UserProfileFormFields kcContext={kcContext} kcClsx={kcClsx} onIsFormSubmittableValueChange={setIsFormSubmittable} />
39
+ <UserProfileFormFields
40
+ kcContext={kcContext}
41
+ kcClsx={kcClsx}
42
+ onIsFormSubmittableValueChange={setIsFormSubmittable}
43
+ doMakeUserConfirmPassword={doMakeUserConfirmPassword}
44
+ />
39
45
 
40
46
  <div className={kcClsx("kcFormGroupClass")}>
41
47
  <div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
@@ -11,22 +11,22 @@ import { rm } from "../bin/tools/fs.rm";
11
11
  import { copyKeycloakResourcesToPublic } from "../bin/shared/copyKeycloakResourcesToPublic";
12
12
  import { assert } from "tsafe/assert";
13
13
  import {
14
- readBuildOptions,
14
+ getBuildContext,
15
+ type BuildContext,
15
16
  type BuildOptions,
16
- type UserProvidedBuildOptions,
17
17
  type ResolvedViteConfig
18
- } from "../bin/shared/buildOptions";
18
+ } from "../bin/shared/buildContext";
19
19
  import MagicString from "magic-string";
20
20
  import { generateKcGenTs } from "../bin/shared/generateKcGenTs";
21
21
 
22
- export type Params = UserProvidedBuildOptions & {
23
- postBuild?: (buildOptions: Omit<BuildOptions, "bundler">) => Promise<void>;
22
+ export type Params = BuildOptions & {
23
+ postBuild?: (buildContext: Omit<BuildContext, "bundler">) => Promise<void>;
24
24
  };
25
25
 
26
26
  export function keycloakify(params?: Params) {
27
- const { postBuild, ...userProvidedBuildOptions } = params ?? {};
27
+ const { postBuild, ...buildOptions } = params ?? {};
28
28
 
29
- let reactAppRootDirPath: string | undefined = undefined;
29
+ let projectDirPath: string | undefined = undefined;
30
30
  let urlPathname: string | undefined = undefined;
31
31
  let buildDirPath: string | undefined = undefined;
32
32
  let command: "build" | "serve" | undefined = undefined;
@@ -45,16 +45,16 @@ export function keycloakify(params?: Params) {
45
45
  break run_post_build_script_case;
46
46
  }
47
47
 
48
- const buildOptions = JSON.parse(envValue) as BuildOptions;
48
+ const buildContext = JSON.parse(envValue) as BuildContext;
49
49
 
50
- await postBuild?.(buildOptions);
50
+ await postBuild?.(buildContext);
51
51
 
52
52
  process.exit(0);
53
53
  }
54
54
 
55
55
  command = resolvedConfig.command;
56
56
 
57
- reactAppRootDirPath = resolvedConfig.root;
57
+ projectDirPath = resolvedConfig.root;
58
58
  urlPathname = (() => {
59
59
  let out = resolvedConfig.env.BASE_URL;
60
60
 
@@ -86,7 +86,7 @@ export function keycloakify(params?: Params) {
86
86
  return out;
87
87
  })();
88
88
 
89
- buildDirPath = pathJoin(reactAppRootDirPath, resolvedConfig.build.outDir);
89
+ buildDirPath = pathJoin(projectDirPath, resolvedConfig.build.outDir);
90
90
 
91
91
  resolve_vite_config_case: {
92
92
  const envValue =
@@ -102,13 +102,13 @@ export function keycloakify(params?: Params) {
102
102
  JSON.stringify(
103
103
  id<ResolvedViteConfig>({
104
104
  publicDir: pathRelative(
105
- reactAppRootDirPath,
105
+ projectDirPath,
106
106
  resolvedConfig.publicDir
107
107
  ),
108
108
  assetsDir: resolvedConfig.build.assetsDir,
109
109
  buildDir: resolvedConfig.build.outDir,
110
110
  urlPathname,
111
- userProvidedBuildOptions
111
+ buildOptions
112
112
  })
113
113
  )
114
114
  );
@@ -116,18 +116,18 @@ export function keycloakify(params?: Params) {
116
116
  process.exit(0);
117
117
  }
118
118
 
119
- const buildOptions = readBuildOptions({
119
+ const buildContext = getBuildContext({
120
120
  cliCommandOptions: {
121
- reactAppRootDirPath
121
+ projectDirPath
122
122
  }
123
123
  });
124
124
 
125
125
  await Promise.all([
126
126
  copyKeycloakResourcesToPublic({
127
- buildOptions
127
+ buildContext
128
128
  }),
129
129
  generateKcGenTs({
130
- buildOptions
130
+ buildContext
131
131
  })
132
132
  ]);
133
133
  },
@@ -139,11 +139,11 @@ export function keycloakify(params?: Params) {
139
139
  return;
140
140
  }
141
141
 
142
- assert(reactAppRootDirPath !== undefined);
142
+ assert(projectDirPath !== undefined);
143
143
 
144
144
  {
145
145
  const isWithinSourceDirectory = id.startsWith(
146
- pathJoin(reactAppRootDirPath, "src") + pathSep
146
+ pathJoin(projectDirPath, "src") + pathSep
147
147
  );
148
148
 
149
149
  if (!isWithinSourceDirectory) {