keycloakify 11.7.4 → 11.8.1

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 (38) hide show
  1. package/bin/{33.index.js → 226.index.js} +2 -19
  2. package/bin/{911.index.js → 297.index.js} +18918 -11359
  3. package/bin/355.index.js +41 -703
  4. package/bin/363.index.js +115 -93
  5. package/bin/369.index.js +968 -0
  6. package/bin/{288.index.js → 502.index.js} +123 -227
  7. package/bin/656.index.js +111 -0
  8. package/bin/{880.index.js → 712.index.js} +227 -216
  9. package/bin/780.index.js +9 -7
  10. package/bin/932.index.js +965 -0
  11. package/bin/97.index.js +2099 -769
  12. package/bin/main.js +66 -49
  13. package/bin/shared/buildContext.d.ts +11 -3
  14. package/bin/start-keycloak/realmConfig/prepareRealmConfig.d.ts +5 -6
  15. package/bin/start-keycloak/realmConfig/realmConfig.d.ts +6 -2
  16. package/package.json +12 -17
  17. package/src/bin/initialize-account-theme/initialize-account-theme.ts +29 -27
  18. package/src/bin/initialize-email-theme.ts +103 -53
  19. package/src/bin/keycloakify/buildJars/buildJar.ts +45 -20
  20. package/src/bin/keycloakify/generateResources/generateResources.ts +263 -217
  21. package/src/bin/shared/{initializeSpa/addSyncExtensionsToPostinstallScript.ts → addSyncExtensionsToPostinstallScript.ts} +1 -1
  22. package/src/bin/shared/buildContext.ts +69 -24
  23. package/src/bin/shared/{initializeSpa/initializeSpa.ts → initializeSpa.ts} +3 -3
  24. package/src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts +12 -23
  25. package/src/bin/start-keycloak/realmConfig/realmConfig.ts +14 -12
  26. package/src/bin/start-keycloak/start-keycloak.ts +55 -28
  27. package/src/bin/sync-extensions/getExtensionModuleFileSourceCodeReadyToBeCopied.ts +6 -0
  28. package/vite-plugin/index.js +48 -20
  29. package/bin/313.index.js +0 -377
  30. package/bin/678.index.js +0 -7565
  31. package/bin/9.index.js +0 -850
  32. package/bin/947.index.js +0 -1565
  33. package/bin/shared/initializeSpa/index.d.ts +0 -1
  34. package/bin/shared/metaInfKeycloakThemes.d.ts +0 -13
  35. package/src/bin/shared/initializeSpa/index.ts +0 -1
  36. package/src/bin/shared/metaInfKeycloakThemes.ts +0 -40
  37. /package/bin/shared/{initializeSpa/addSyncExtensionsToPostinstallScript.d.ts → addSyncExtensionsToPostinstallScript.d.ts} +0 -0
  38. /package/bin/shared/{initializeSpa/initializeSpa.d.ts → initializeSpa.d.ts} +0 -0
@@ -15,7 +15,6 @@ import { readFileSync } from "fs";
15
15
  import { isInside } from "../../tools/isInside";
16
16
  import child_process from "child_process";
17
17
  import { rmSync } from "../../tools/fs.rmSync";
18
- import { writeMetaInfKeycloakThemes } from "../../shared/metaInfKeycloakThemes";
19
18
  import { existsAsync } from "../../tools/fs.existsAsync";
20
19
 
21
20
  export type BuildContextLike = BuildContextLike_generatePom & {
@@ -106,29 +105,55 @@ export async function buildJar(params: {
106
105
  }
107
106
  });
108
107
 
109
- remove_account_v1_in_meta_inf: {
110
- if (!doesImplementAccountV1Theme) {
111
- // NOTE: We do not have account v1 anyway
112
- break remove_account_v1_in_meta_inf;
113
- }
108
+ {
109
+ const filePath = pathJoin(
110
+ tmpResourcesDirPath,
111
+ "META-INF",
112
+ "keycloak-themes.json"
113
+ );
114
114
 
115
- if (keycloakAccountV1Version !== null) {
116
- // NOTE: No, we need to keep account-v1 in meta-inf
117
- break remove_account_v1_in_meta_inf;
118
- }
115
+ await fs.mkdir(pathDirname(filePath));
119
116
 
120
- writeMetaInfKeycloakThemes({
121
- resourcesDirPath: tmpResourcesDirPath,
122
- getNewMetaInfKeycloakTheme: ({ metaInfKeycloakTheme }) => {
123
- assert(metaInfKeycloakTheme !== undefined);
117
+ await fs.writeFile(
118
+ filePath,
119
+ Buffer.from(
120
+ JSON.stringify(
121
+ {
122
+ themes: await (async () => {
123
+ const dirPath = pathJoin(tmpResourcesDirPath, "theme");
124
124
 
125
- metaInfKeycloakTheme.themes = metaInfKeycloakTheme.themes.filter(
126
- ({ name }) => name !== "account-v1"
127
- );
125
+ const themeNames = (await fs.readdir(dirPath)).sort(
126
+ (a, b) => {
127
+ const indexA = buildContext.themeNames.indexOf(a);
128
+ const indexB = buildContext.themeNames.indexOf(b);
128
129
 
129
- return metaInfKeycloakTheme;
130
- }
131
- });
130
+ const orderA = indexA === -1 ? Infinity : indexA;
131
+ const orderB = indexB === -1 ? Infinity : indexB;
132
+
133
+ return orderA - orderB;
134
+ }
135
+ );
136
+
137
+ return Promise.all(
138
+ themeNames.map(async themeName => {
139
+ const types = await fs.readdir(
140
+ pathJoin(dirPath, themeName)
141
+ );
142
+
143
+ return {
144
+ name: themeName,
145
+ types
146
+ };
147
+ })
148
+ );
149
+ })()
150
+ },
151
+ null,
152
+ 2
153
+ ),
154
+ "utf8"
155
+ )
156
+ );
132
157
  }
133
158
 
134
159
  route_legacy_pages: {
@@ -31,16 +31,12 @@ import {
31
31
  type BuildContextLike as BuildContextLike_generateMessageProperties
32
32
  } from "./generateMessageProperties";
33
33
  import { readThisNpmPackageVersion } from "../../tools/readThisNpmPackageVersion";
34
- import {
35
- writeMetaInfKeycloakThemes,
36
- type MetaInfKeycloakTheme
37
- } from "../../shared/metaInfKeycloakThemes";
38
- import { objectEntries } from "tsafe/objectEntries";
39
34
  import { escapeStringForPropertiesFile } from "../../tools/escapeStringForPropertiesFile";
40
35
  import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
41
36
  import propertiesParser from "properties-parser";
42
37
  import { createObjectThatThrowsIfAccessed } from "../../tools/createObjectThatThrowsIfAccessed";
43
38
  import { listInstalledModules } from "../../tools/listInstalledModules";
39
+ import { isInside } from "../../tools/isInside";
44
40
 
45
41
  export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode &
46
42
  BuildContextLike_generateMessageProperties & {
@@ -78,12 +74,23 @@ export async function generateResources(params: {
78
74
  };
79
75
 
80
76
  const writeMessagePropertiesFilesByThemeType: Partial<
81
- Record<ThemeType, (params: { messageDirPath: string; themeName: string }) => void>
77
+ Record<
78
+ ThemeType | "email",
79
+ (params: { messageDirPath: string; themeName: string }) => void
80
+ >
82
81
  > = {};
83
82
 
84
- for (const themeType of THEME_TYPES) {
85
- if (!buildContext.implementedThemeTypes[themeType].isImplemented) {
86
- continue;
83
+ for (const themeType of [...THEME_TYPES, "email"] as const) {
84
+ let isNative: boolean;
85
+
86
+ {
87
+ const v = buildContext.implementedThemeTypes[themeType];
88
+
89
+ if (!v.isImplemented && !v.isImplemented_native) {
90
+ continue;
91
+ }
92
+
93
+ isNative = !v.isImplemented && v.isImplemented_native;
87
94
  }
88
95
 
89
96
  const getAccountThemeType = () => {
@@ -102,12 +109,18 @@ export async function generateResources(params: {
102
109
  return getAccountThemeType() === "Single-Page";
103
110
  case "admin":
104
111
  return true;
112
+ case "email":
113
+ return false;
105
114
  }
106
115
  })();
107
116
 
108
117
  const themeTypeDirPath = getThemeTypeDirPath({ themeName, themeType });
109
118
 
110
119
  apply_replacers_and_move_to_theme_resources: {
120
+ if (isNative) {
121
+ break apply_replacers_and_move_to_theme_resources;
122
+ }
123
+
111
124
  const destDirPath = pathJoin(
112
125
  themeTypeDirPath,
113
126
  "resources",
@@ -191,59 +204,93 @@ export async function generateResources(params: {
191
204
  });
192
205
  }
193
206
 
194
- const { generateFtlFilesCode } = generateFtlFilesCodeFactory({
195
- themeName,
196
- indexHtmlCode: fs
197
- .readFileSync(pathJoin(buildContext.projectBuildDirPath, "index.html"))
198
- .toString("utf8"),
199
- buildContext,
200
- keycloakifyVersion: readThisNpmPackageVersion(),
201
- themeType,
202
- fieldNames: isSpa
203
- ? []
204
- : (assert(themeType !== "admin"),
205
- readFieldNameUsage({
206
- themeSrcDirPath: buildContext.themeSrcDirPath,
207
- themeType
208
- }))
209
- });
210
-
211
- [
212
- ...(() => {
213
- switch (themeType) {
214
- case "login":
215
- return LOGIN_THEME_PAGE_IDS;
216
- case "account":
217
- return getAccountThemeType() === "Single-Page"
218
- ? ["index.ftl"]
219
- : ACCOUNT_THEME_PAGE_IDS;
220
- case "admin":
221
- return ["index.ftl"];
222
- }
223
- })(),
224
- ...(isSpa
225
- ? []
226
- : readExtraPagesNames({
227
- themeType,
228
- themeSrcDirPath: buildContext.themeSrcDirPath
229
- }))
230
- ].forEach(pageId => {
231
- const { ftlCode } = generateFtlFilesCode({ pageId });
207
+ generate_ftl_files: {
208
+ if (isNative) {
209
+ break generate_ftl_files;
210
+ }
232
211
 
233
- fs.writeFileSync(
234
- pathJoin(themeTypeDirPath, pageId),
235
- Buffer.from(ftlCode, "utf8")
236
- );
237
- });
212
+ assert(themeType !== "email");
213
+
214
+ const { generateFtlFilesCode } = generateFtlFilesCodeFactory({
215
+ themeName,
216
+ indexHtmlCode: fs
217
+ .readFileSync(
218
+ pathJoin(buildContext.projectBuildDirPath, "index.html")
219
+ )
220
+ .toString("utf8"),
221
+ buildContext,
222
+ keycloakifyVersion: readThisNpmPackageVersion(),
223
+ themeType,
224
+ fieldNames: isSpa
225
+ ? []
226
+ : (assert(themeType !== "admin"),
227
+ readFieldNameUsage({
228
+ themeSrcDirPath: buildContext.themeSrcDirPath,
229
+ themeType
230
+ }))
231
+ });
232
+
233
+ [
234
+ ...(() => {
235
+ switch (themeType) {
236
+ case "login":
237
+ return LOGIN_THEME_PAGE_IDS;
238
+ case "account":
239
+ return getAccountThemeType() === "Single-Page"
240
+ ? ["index.ftl"]
241
+ : ACCOUNT_THEME_PAGE_IDS;
242
+ case "admin":
243
+ return ["index.ftl"];
244
+ }
245
+ })(),
246
+ ...(isSpa
247
+ ? []
248
+ : readExtraPagesNames({
249
+ themeType,
250
+ themeSrcDirPath: buildContext.themeSrcDirPath
251
+ }))
252
+ ].forEach(pageId => {
253
+ const { ftlCode } = generateFtlFilesCode({ pageId });
254
+
255
+ fs.writeFileSync(
256
+ pathJoin(themeTypeDirPath, pageId),
257
+ Buffer.from(ftlCode, "utf8")
258
+ );
259
+ });
260
+ }
261
+
262
+ copy_native_theme: {
263
+ if (!isNative) {
264
+ break copy_native_theme;
265
+ }
266
+
267
+ const dirPath = pathJoin(buildContext.themeSrcDirPath, themeType);
268
+
269
+ transformCodebase({
270
+ srcDirPath: dirPath,
271
+ destDirPath: getThemeTypeDirPath({ themeName, themeType }),
272
+ transformSourceCode: ({ fileRelativePath, sourceCode }) => {
273
+ if (isInside({ dirPath: "messages", filePath: fileRelativePath })) {
274
+ return undefined;
275
+ }
276
+
277
+ return { modifiedSourceCode: sourceCode };
278
+ }
279
+ });
280
+ }
238
281
 
239
282
  let languageTags: string[] | undefined = undefined;
240
283
 
241
284
  i18n_multi_page: {
285
+ if (isNative) {
286
+ break i18n_multi_page;
287
+ }
288
+
242
289
  if (isSpa) {
243
290
  break i18n_multi_page;
244
291
  }
245
292
 
246
- assert(themeType !== "admin");
293
+ assert(themeType !== "admin" && themeType !== "email");
247
294
 
248
295
  const wrap = generateMessageProperties({
249
296
  buildContext,
@@ -364,27 +411,24 @@ export async function generateResources(params: {
364
411
  );
365
412
  }
366
413
 
367
- i18n_single_page: {
368
- if (!isSpa) {
369
- break i18n_single_page;
414
+ i18n_for_spas_and_native: {
415
+ if (!isSpa && !isNative) {
416
+ break i18n_for_spas_and_native;
370
417
  }
371
418
 
372
419
  if (isLegacyAccountSpa) {
373
- break i18n_single_page;
420
+ break i18n_for_spas_and_native;
374
421
  }
375
422
 
376
- assert(themeType === "account" || themeType === "admin");
377
-
378
423
  const messagesDirPath_theme = pathJoin(
379
424
  buildContext.themeSrcDirPath,
380
425
  themeType,
381
- "i18n"
426
+ isNative ? "messages" : "i18n"
382
427
  );
383
428
 
384
- assert(
385
- fs.existsSync(messagesDirPath_theme),
386
- `${messagesDirPath_theme} is supposed to exist`
387
- );
429
+ if (!fs.existsSync(messagesDirPath_theme)) {
430
+ break i18n_for_spas_and_native;
431
+ }
388
432
 
389
433
  const propertiesByLang: Record<
390
434
  string,
@@ -524,6 +568,10 @@ export async function generateResources(params: {
524
568
  }
525
569
 
526
570
  keycloak_static_resources: {
571
+ if (isNative) {
572
+ break keycloak_static_resources;
573
+ }
574
+
527
575
  if (isSpa) {
528
576
  break keycloak_static_resources;
529
577
  }
@@ -540,183 +588,181 @@ export async function generateResources(params: {
540
588
  });
541
589
  }
542
590
 
543
- fs.writeFileSync(
544
- pathJoin(themeTypeDirPath, "theme.properties"),
545
- Buffer.from(
546
- [
547
- `parent=${(() => {
548
- switch (themeType) {
549
- case "account":
550
- switch (getAccountThemeType()) {
551
- case "Multi-Page":
552
- return "account-v1";
553
- case "Single-Page":
554
- return "base";
555
- }
556
- case "login":
557
- return "keycloak";
558
- case "admin":
559
- return "base";
560
- }
561
- assert<Equals<typeof themeType, never>>(false);
562
- })()}`,
563
- ...(themeType === "account" && getAccountThemeType() === "Single-Page"
564
- ? ["deprecatedMode=false"]
565
- : []),
566
- ...(buildContext.extraThemeProperties ?? []),
567
- ...[
568
- ...buildContext.environmentVariables,
569
- { name: KEYCLOAKIFY_SPA_DEV_SERVER_PORT, default: "" }
570
- ].map(
571
- ({ name, default: defaultValue }) =>
572
- `${name}=\${env.${name}:${escapeStringForPropertiesFile(defaultValue)}}`
573
- ),
574
- ...(languageTags === undefined
575
- ? []
576
- : [`locales=${languageTags.join(",")}`])
577
- ].join("\n\n"),
578
- "utf8"
579
- )
580
- );
581
- }
582
-
583
- email: {
584
- if (!buildContext.implementedThemeTypes.email.isImplemented) {
585
- break email;
586
- }
591
+ bring_in_account_v1: {
592
+ if (isNative) {
593
+ break bring_in_account_v1;
594
+ }
587
595
 
588
- const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
596
+ if (themeType !== "account") {
597
+ break bring_in_account_v1;
598
+ }
589
599
 
590
- transformCodebase({
591
- srcDirPath: emailThemeSrcDirPath,
592
- destDirPath: getThemeTypeDirPath({ themeName, themeType: "email" })
593
- });
594
- }
600
+ assert(buildContext.implementedThemeTypes.account.isImplemented);
595
601
 
596
- bring_in_account_v1: {
597
- if (!buildContext.implementedThemeTypes.account.isImplemented) {
598
- break bring_in_account_v1;
599
- }
602
+ if (buildContext.implementedThemeTypes.account.type !== "Multi-Page") {
603
+ break bring_in_account_v1;
604
+ }
600
605
 
601
- if (buildContext.implementedThemeTypes.account.type !== "Multi-Page") {
602
- break bring_in_account_v1;
606
+ transformCodebase({
607
+ srcDirPath: pathJoin(getThisCodebaseRootDirPath(), "res", "account-v1"),
608
+ destDirPath: getThemeTypeDirPath({
609
+ themeName: "account-v1",
610
+ themeType: "account"
611
+ })
612
+ });
603
613
  }
604
614
 
605
- transformCodebase({
606
- srcDirPath: pathJoin(getThisCodebaseRootDirPath(), "res", "account-v1"),
607
- destDirPath: getThemeTypeDirPath({
608
- themeName: "account-v1",
609
- themeType: "account"
610
- })
611
- });
612
- }
613
-
614
- {
615
- const metaInfKeycloakThemes: MetaInfKeycloakTheme = { themes: [] };
615
+ generate_theme_properties: {
616
+ if (isNative) {
617
+ break generate_theme_properties;
618
+ }
616
619
 
617
- for (const themeName of buildContext.themeNames) {
618
- metaInfKeycloakThemes.themes.push({
619
- name: themeName,
620
- types: objectEntries(buildContext.implementedThemeTypes)
621
- .filter(([, { isImplemented }]) => isImplemented)
622
- .map(([themeType]) => themeType)
623
- });
624
- }
620
+ assert(themeType !== "email");
625
621
 
626
- if (buildContext.implementedThemeTypes.account.isImplemented) {
627
- metaInfKeycloakThemes.themes.push({
628
- name: "account-v1",
629
- types: ["account"]
630
- });
622
+ fs.writeFileSync(
623
+ pathJoin(themeTypeDirPath, "theme.properties"),
624
+ Buffer.from(
625
+ [
626
+ `parent=${(() => {
627
+ switch (themeType) {
628
+ case "account":
629
+ switch (getAccountThemeType()) {
630
+ case "Multi-Page":
631
+ return "account-v1";
632
+ case "Single-Page":
633
+ return "base";
634
+ }
635
+ case "login":
636
+ return "keycloak";
637
+ case "admin":
638
+ return "base";
639
+ }
640
+ assert<Equals<typeof themeType, never>>;
641
+ })()}`,
642
+ ...(themeType === "account" &&
643
+ getAccountThemeType() === "Single-Page"
644
+ ? ["deprecatedMode=false"]
645
+ : []),
646
+ ...(buildContext.extraThemeProperties ?? []),
647
+ ...[
648
+ ...buildContext.environmentVariables,
649
+ { name: KEYCLOAKIFY_SPA_DEV_SERVER_PORT, default: "" }
650
+ ].map(
651
+ ({ name, default: defaultValue }) =>
652
+ `${name}=\${env.${name}:${escapeStringForPropertiesFile(defaultValue)}}`
653
+ ),
654
+ ...(languageTags === undefined
655
+ ? []
656
+ : [`locales=${languageTags.join(",")}`])
657
+ ].join("\n\n"),
658
+ "utf8"
659
+ )
660
+ );
631
661
  }
632
-
633
- writeMetaInfKeycloakThemes({
634
- resourcesDirPath,
635
- getNewMetaInfKeycloakTheme: () => metaInfKeycloakThemes
636
- });
637
662
  }
638
663
 
639
664
  for (const themeVariantName of buildContext.themeNames) {
640
- if (themeVariantName === themeName) {
641
- continue;
642
- }
665
+ for (const themeType of [...THEME_TYPES, "email"] as const) {
666
+ copy_main_theme_to_theme_variant_theme: {
667
+ let isNative: boolean;
643
668
 
644
- transformCodebase({
645
- srcDirPath: pathJoin(resourcesDirPath, "theme", themeName),
646
- destDirPath: pathJoin(resourcesDirPath, "theme", themeVariantName),
647
- transformSourceCode: ({ fileRelativePath, sourceCode }) => {
648
- if (
649
- pathExtname(fileRelativePath) === ".ftl" &&
650
- fileRelativePath.split(pathSep).length === 2
651
- ) {
652
- const modifiedSourceCode = Buffer.from(
653
- Buffer.from(sourceCode)
654
- .toString("utf-8")
655
- .replace(
656
- `"themeName": "${themeName}"`,
657
- `"themeName": "${themeVariantName}"`
658
- ),
659
- "utf8"
660
- );
669
+ {
670
+ const v = buildContext.implementedThemeTypes[themeType];
661
671
 
662
- assert(Buffer.compare(modifiedSourceCode, sourceCode) !== 0);
672
+ if (!v.isImplemented && !v.isImplemented_native) {
673
+ break copy_main_theme_to_theme_variant_theme;
674
+ }
663
675
 
664
- return { modifiedSourceCode };
676
+ isNative = !v.isImplemented && v.isImplemented_native;
665
677
  }
666
678
 
667
- return { modifiedSourceCode: sourceCode };
668
- }
669
- });
670
- }
679
+ if (themeVariantName === themeName) {
680
+ break copy_main_theme_to_theme_variant_theme;
681
+ }
671
682
 
672
- for (const themeName of buildContext.themeNames) {
673
- for (const [themeType, writeMessagePropertiesFiles] of objectEntries(
674
- writeMessagePropertiesFilesByThemeType
675
- )) {
676
- // NOTE: This is just a quirk of the type system: We can't really differentiate in a record
677
- // between the case where the key isn't present and the case where the value is `undefined`.
678
- if (writeMessagePropertiesFiles === undefined) {
679
- return;
683
+ transformCodebase({
684
+ srcDirPath: pathJoin(resourcesDirPath, "theme", themeName),
685
+ destDirPath: pathJoin(resourcesDirPath, "theme", themeVariantName),
686
+ transformSourceCode: isNative
687
+ ? undefined
688
+ : ({ fileRelativePath, sourceCode }) => {
689
+ if (
690
+ pathExtname(fileRelativePath) === ".ftl" &&
691
+ fileRelativePath.split(pathSep).length === 2
692
+ ) {
693
+ const modifiedSourceCode = Buffer.from(
694
+ Buffer.from(sourceCode)
695
+ .toString("utf-8")
696
+ .replace(
697
+ `"themeName": "${themeName}"`,
698
+ `"themeName": "${themeVariantName}"`
699
+ ),
700
+ "utf8"
701
+ );
702
+
703
+ assert(
704
+ Buffer.compare(modifiedSourceCode, sourceCode) !== 0
705
+ );
706
+
707
+ return { modifiedSourceCode };
708
+ }
709
+
710
+ return { modifiedSourceCode: sourceCode };
711
+ }
712
+ });
680
713
  }
681
- writeMessagePropertiesFiles({
682
- messageDirPath: pathJoin(
683
- getThemeTypeDirPath({ themeName, themeType }),
684
- "messages"
685
- ),
686
- themeName
687
- });
688
- }
689
- }
714
+ run_writeMessagePropertiesFiles: {
715
+ const writeMessagePropertiesFiles =
716
+ writeMessagePropertiesFilesByThemeType[themeType];
690
717
 
691
- modify_email_theme_per_variant: {
692
- if (!buildContext.implementedThemeTypes.email.isImplemented) {
693
- break modify_email_theme_per_variant;
694
- }
718
+ if (writeMessagePropertiesFiles === undefined) {
719
+ break run_writeMessagePropertiesFiles;
720
+ }
695
721
 
696
- for (const themeName of buildContext.themeNames) {
697
- const emailThemeDirPath = getThemeTypeDirPath({
698
- themeName,
699
- themeType: "email"
700
- });
722
+ writeMessagePropertiesFiles({
723
+ messageDirPath: pathJoin(
724
+ getThemeTypeDirPath({ themeName: themeVariantName, themeType }),
725
+ "messages"
726
+ ),
727
+ themeName: themeVariantName
728
+ });
729
+ }
730
+ replace_xKeycloakify_themeName_in_native_ftl_files: {
731
+ {
732
+ const v = buildContext.implementedThemeTypes[themeType];
701
733
 
702
- transformCodebase({
703
- srcDirPath: emailThemeDirPath,
704
- destDirPath: emailThemeDirPath,
705
- transformSourceCode: ({ filePath, sourceCode }) => {
706
- if (!filePath.endsWith(".ftl")) {
707
- return { modifiedSourceCode: sourceCode };
734
+ if (v.isImplemented || !v.isImplemented_native) {
735
+ break replace_xKeycloakify_themeName_in_native_ftl_files;
708
736
  }
709
-
710
- return {
711
- modifiedSourceCode: Buffer.from(
712
- sourceCode
713
- .toString("utf8")
714
- .replace(/xKeycloakify\.themeName/g, `"${themeName}"`),
715
- "utf8"
716
- )
717
- };
718
737
  }
719
- });
738
+
739
+ const emailThemeDirPath = getThemeTypeDirPath({
740
+ themeName,
741
+ themeType
742
+ });
743
+
744
+ transformCodebase({
745
+ srcDirPath: emailThemeDirPath,
746
+ destDirPath: emailThemeDirPath,
747
+ transformSourceCode: ({ filePath, sourceCode }) => {
748
+ if (!filePath.endsWith(".ftl")) {
749
+ return { modifiedSourceCode: sourceCode };
750
+ }
751
+
752
+ return {
753
+ modifiedSourceCode: Buffer.from(
754
+ sourceCode
755
+ .toString("utf8")
756
+ .replace(
757
+ /xKeycloakify\.themeName/g,
758
+ `"${themeName}"`
759
+ ),
760
+ "utf8"
761
+ )
762
+ };
763
+ }
764
+ });
765
+ }
720
766
  }
721
767
  }
722
768
  }
@@ -1,6 +1,6 @@
1
1
  import { dirname as pathDirname, relative as pathRelative, sep as pathSep } from "path";
2
2
  import { assert } from "tsafe/assert";
3
- import type { BuildContext } from "../buildContext";
3
+ import type { BuildContext } from "./buildContext";
4
4
 
5
5
  export type BuildContextLike = {
6
6
  projectDirPath: string;