keycloakify 7.12.7 → 7.13.0

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 (40) hide show
  1. package/README.md +4 -0
  2. package/bin/getSrcDirPath.d.ts +0 -5
  3. package/bin/getSrcDirPath.js +1 -8
  4. package/bin/getSrcDirPath.js.map +1 -1
  5. package/bin/initialize-email-theme.js +5 -4
  6. package/bin/initialize-email-theme.js.map +1 -1
  7. package/bin/keycloakify/BuildOptions.d.ts +0 -1
  8. package/bin/keycloakify/BuildOptions.js +4 -5
  9. package/bin/keycloakify/BuildOptions.js.map +1 -1
  10. package/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +6 -12
  11. package/bin/keycloakify/generateFtl/generateFtl.d.ts +1 -1
  12. package/bin/keycloakify/generateFtl/generateFtl.js +2 -2
  13. package/bin/keycloakify/generateFtl/generateFtl.js.map +1 -1
  14. package/bin/keycloakify/generateJavaStackFiles.d.ts +2 -1
  15. package/bin/keycloakify/generateJavaStackFiles.js +10 -3
  16. package/bin/keycloakify/generateJavaStackFiles.js.map +1 -1
  17. package/bin/keycloakify/generateStartKeycloakTestingContainer.js.map +1 -1
  18. package/bin/keycloakify/generateTheme/generateTheme.d.ts +3 -5
  19. package/bin/keycloakify/generateTheme/generateTheme.js +15 -7
  20. package/bin/keycloakify/generateTheme/generateTheme.js.map +1 -1
  21. package/bin/keycloakify/generateTheme/readFieldNameUsage.d.ts +6 -0
  22. package/bin/keycloakify/generateTheme/readFieldNameUsage.js +162 -0
  23. package/bin/keycloakify/generateTheme/readFieldNameUsage.js.map +1 -0
  24. package/bin/keycloakify/keycloakify.js +40 -15
  25. package/bin/keycloakify/keycloakify.js.map +1 -1
  26. package/bin/keycloakify/parsedPackageJson.d.ts +0 -7
  27. package/bin/keycloakify/parsedPackageJson.js +0 -1
  28. package/bin/keycloakify/parsedPackageJson.js.map +1 -1
  29. package/package.json +176 -1
  30. package/src/bin/getSrcDirPath.ts +0 -10
  31. package/src/bin/initialize-email-theme.ts +5 -3
  32. package/src/bin/keycloakify/BuildOptions.ts +1 -3
  33. package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +6 -12
  34. package/src/bin/keycloakify/generateFtl/generateFtl.ts +3 -6
  35. package/src/bin/keycloakify/generateJavaStackFiles.ts +6 -4
  36. package/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts +0 -1
  37. package/src/bin/keycloakify/generateTheme/generateTheme.ts +17 -12
  38. package/src/bin/keycloakify/generateTheme/readFieldNameUsage.ts +96 -0
  39. package/src/bin/keycloakify/keycloakify.ts +33 -20
  40. package/src/bin/keycloakify/parsedPackageJson.ts +0 -2
@@ -9,6 +9,7 @@ import { isInside } from "../../tools/isInside";
9
9
  import type { BuildOptions } from "../BuildOptions";
10
10
  import { assert } from "tsafe/assert";
11
11
  import { downloadKeycloakStaticResources } from "./downloadKeycloakStaticResources";
12
+ import { readFieldNameUsage } from "./readFieldNameUsage";
12
13
 
13
14
  export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
14
15
 
@@ -19,7 +20,6 @@ export namespace BuildOptionsLike {
19
20
  extraAccountPages?: string[];
20
21
  extraThemeProperties?: string[];
21
22
  isSilent: boolean;
22
- customUserAttributes: string[];
23
23
  themeVersion: string;
24
24
  keycloakVersionDefaultAssets: string;
25
25
  };
@@ -53,11 +53,12 @@ assert<BuildOptions extends BuildOptionsLike ? true : false>();
53
53
  export async function generateTheme(params: {
54
54
  reactAppBuildDirPath: string;
55
55
  keycloakThemeBuildingDirPath: string;
56
- emailThemeSrcDirPath: string | undefined;
56
+ themeSrcDirPath: string | undefined;
57
+ keycloakifySrcDirPath: string;
57
58
  buildOptions: BuildOptionsLike;
58
59
  keycloakifyVersion: string;
59
- }): Promise<{ doBundlesEmailTemplate: boolean }> {
60
- const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, buildOptions, keycloakifyVersion } = params;
60
+ }): Promise<void> {
61
+ const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params;
61
62
 
62
63
  const getThemeDirPath = (themeType: ThemeType | "email") =>
63
64
  pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, themeType);
@@ -142,7 +143,12 @@ export async function generateTheme(params: {
142
143
  "cssGlobalsToDefine": allCssGlobalsToDefine,
143
144
  buildOptions,
144
145
  keycloakifyVersion,
145
- themeType
146
+ themeType,
147
+ "fieldNames": readFieldNameUsage({
148
+ keycloakifySrcDirPath,
149
+ themeSrcDirPath,
150
+ themeType
151
+ })
146
152
  });
147
153
 
148
154
  return generateFtlFilesCode;
@@ -220,21 +226,20 @@ export async function generateTheme(params: {
220
226
  );
221
227
  }
222
228
 
223
- let doBundlesEmailTemplate: boolean;
224
-
225
229
  email: {
226
- if (emailThemeSrcDirPath === undefined) {
227
- doBundlesEmailTemplate = false;
230
+ if (themeSrcDirPath === undefined) {
228
231
  break email;
229
232
  }
230
233
 
231
- doBundlesEmailTemplate = true;
234
+ const emailThemeSrcDirPath = pathJoin(themeSrcDirPath, "email");
235
+
236
+ if (!fs.existsSync(emailThemeSrcDirPath)) {
237
+ break email;
238
+ }
232
239
 
233
240
  transformCodebase({
234
241
  "srcDirPath": emailThemeSrcDirPath,
235
242
  "destDirPath": getThemeDirPath("email")
236
243
  });
237
244
  }
238
-
239
- return { doBundlesEmailTemplate };
240
245
  }
@@ -0,0 +1,96 @@
1
+ import { crawl } from "../../tools/crawl";
2
+ import { removeDuplicates } from "evt/tools/reducers/removeDuplicates";
3
+ import { join as pathJoin } from "path";
4
+ import * as fs from "fs";
5
+ import type { ThemeType } from "../generateFtl";
6
+ import { exclude } from "tsafe/exclude";
7
+
8
+ export function readFieldNameUsage(params: {
9
+ keycloakifySrcDirPath: string;
10
+ themeSrcDirPath: string | undefined;
11
+ themeType: ThemeType | "email";
12
+ }): string[] {
13
+ const { keycloakifySrcDirPath, themeSrcDirPath, themeType } = params;
14
+
15
+ const fieldNames: string[] = [];
16
+
17
+ if (themeSrcDirPath === undefined) {
18
+ //If we can't detect the user theme directory we restore the fieldNames we had previously to prevent errors.
19
+ fieldNames.push(
20
+ ...[
21
+ "global",
22
+ "userLabel",
23
+ "username",
24
+ "email",
25
+ "firstName",
26
+ "lastName",
27
+ "password",
28
+ "password-confirm",
29
+ "totp",
30
+ "totpSecret",
31
+ "SAMLRequest",
32
+ "SAMLResponse",
33
+ "relayState",
34
+ "device_user_code",
35
+ "code",
36
+ "password-new",
37
+ "rememberMe",
38
+ "login",
39
+ "authenticationExecution",
40
+ "cancel-aia",
41
+ "clientDataJSON",
42
+ "authenticatorData",
43
+ "signature",
44
+ "credentialId",
45
+ "userHandle",
46
+ "error",
47
+ "authn_use_chk",
48
+ "authenticationExecution",
49
+ "isSetRetry",
50
+ "try-again",
51
+ "attestationObject",
52
+ "publicKeyCredentialId",
53
+ "authenticatorLabel"
54
+ ]
55
+ );
56
+ }
57
+
58
+ for (const srcDirPath of (
59
+ [
60
+ pathJoin(keycloakifySrcDirPath, themeType),
61
+ (() => {
62
+ if (themeSrcDirPath === undefined) {
63
+ return undefined;
64
+ }
65
+
66
+ const srcDirPath = pathJoin(themeSrcDirPath, themeType);
67
+
68
+ if (!fs.existsSync(srcDirPath)) {
69
+ return undefined;
70
+ }
71
+
72
+ return srcDirPath;
73
+ })()
74
+ ] as const
75
+ ).filter(exclude(undefined))) {
76
+ const filePaths = crawl(srcDirPath)
77
+ .filter(filePath => /\.(ts|tsx|js|jsx)$/.test(filePath))
78
+ .map(filePath => pathJoin(srcDirPath, filePath));
79
+
80
+ for (const filePath of filePaths) {
81
+ const rawSourceFile = fs.readFileSync(filePath).toString("utf8");
82
+
83
+ if (!rawSourceFile.includes("messagesPerField")) {
84
+ continue;
85
+ }
86
+
87
+ fieldNames.push(
88
+ ...Array.from(rawSourceFile.matchAll(/(?:(?:printIfExists)|(?:existsError)|(?:get)|(?:exists))\(["']([^"']+)["']/g), m => m[1])
89
+ );
90
+ }
91
+ }
92
+
93
+ const out = fieldNames.reduce(...removeDuplicates<string>());
94
+
95
+ return out;
96
+ }
@@ -9,8 +9,9 @@ import { getLogger } from "../tools/logger";
9
9
  import jar from "../tools/jar";
10
10
  import { assert } from "tsafe/assert";
11
11
  import { Equals } from "tsafe";
12
- import { getEmailThemeSrcDirPath } from "../getSrcDirPath";
12
+ import { getThemeSrcDirPath } from "../getSrcDirPath";
13
13
  import { getProjectRoot } from "../tools/getProjectRoot";
14
+ import { objectKeys } from "tsafe/objectKeys";
14
15
 
15
16
  export async function main() {
16
17
  const projectDirPath = process.cwd();
@@ -23,42 +24,54 @@ export async function main() {
23
24
  const logger = getLogger({ "isSilent": buildOptions.isSilent });
24
25
  logger.log("🔏 Building the keycloak theme...⌚");
25
26
 
26
- let doBundlesEmailTemplate: boolean | undefined;
27
+ const keycloakifyDirPath = getProjectRoot();
27
28
 
28
- for (const themeName of [buildOptions.themeName, ...buildOptions.extraThemeNames]) {
29
- const { doBundlesEmailTemplate: doBundlesEmailTemplate_ } = await generateTheme({
30
- keycloakThemeBuildingDirPath: buildOptions.keycloakifyBuildDirPath,
31
- "emailThemeSrcDirPath": (() => {
32
- const { emailThemeSrcDirPath } = getEmailThemeSrcDirPath({ projectDirPath });
33
-
34
- if (emailThemeSrcDirPath === undefined || !fs.existsSync(emailThemeSrcDirPath)) {
35
- return;
36
- }
29
+ const { themeSrcDirPath } = getThemeSrcDirPath({ projectDirPath });
37
30
 
38
- return emailThemeSrcDirPath;
39
- })(),
31
+ for (const themeName of [buildOptions.themeName, ...buildOptions.extraThemeNames]) {
32
+ await generateTheme({
33
+ "keycloakThemeBuildingDirPath": buildOptions.keycloakifyBuildDirPath,
34
+ themeSrcDirPath,
35
+ "keycloakifySrcDirPath": pathJoin(keycloakifyDirPath, "src"),
40
36
  "reactAppBuildDirPath": buildOptions.reactAppBuildDirPath,
41
37
  "buildOptions": {
42
38
  ...buildOptions,
43
39
  "themeName": themeName
44
40
  },
45
41
  "keycloakifyVersion": (() => {
46
- const version = JSON.parse(fs.readFileSync(pathJoin(getProjectRoot(), "package.json")).toString("utf8"))["version"];
42
+ const version = JSON.parse(fs.readFileSync(pathJoin(keycloakifyDirPath, "package.json")).toString("utf8"))["version"];
47
43
 
48
44
  assert(typeof version === "string");
49
45
 
50
46
  return version;
51
47
  })()
52
48
  });
53
-
54
- doBundlesEmailTemplate ??= doBundlesEmailTemplate_;
55
49
  }
56
50
 
57
- assert(doBundlesEmailTemplate !== undefined);
58
-
59
51
  const { jarFilePath } = generateJavaStackFiles({
60
- keycloakThemeBuildingDirPath: buildOptions.keycloakifyBuildDirPath,
61
- doBundlesEmailTemplate,
52
+ "keycloakThemeBuildingDirPath": buildOptions.keycloakifyBuildDirPath,
53
+ "implementedThemeTypes": (() => {
54
+ const implementedThemeTypes = {
55
+ "login": false,
56
+ "account": false,
57
+ "email": false
58
+ };
59
+
60
+ if (themeSrcDirPath === undefined) {
61
+ implementedThemeTypes["login"] = true;
62
+ implementedThemeTypes["account"] = true;
63
+ return implementedThemeTypes;
64
+ }
65
+
66
+ for (const themeType of objectKeys(implementedThemeTypes)) {
67
+ if (!fs.existsSync(pathJoin(themeSrcDirPath, themeType))) {
68
+ continue;
69
+ }
70
+ implementedThemeTypes[themeType] = true;
71
+ }
72
+
73
+ return implementedThemeTypes;
74
+ })(),
62
75
  buildOptions
63
76
  });
64
77
 
@@ -23,7 +23,6 @@ export type ParsedPackageJson = {
23
23
  keycloakVersionDefaultAssets?: string;
24
24
  reactAppBuildDirPath?: string;
25
25
  keycloakifyBuildDirPath?: string;
26
- customUserAttributes?: string[];
27
26
  themeName?: string;
28
27
  extraThemeNames?: string[];
29
28
  };
@@ -46,7 +45,6 @@ export const zParsedPackageJson = z.object({
46
45
  "keycloakVersionDefaultAssets": z.string().optional(),
47
46
  "reactAppBuildDirPath": z.string().optional(),
48
47
  "keycloakifyBuildDirPath": z.string().optional(),
49
- "customUserAttributes": z.array(z.string()).optional(),
50
48
  "themeName": z.string().optional(),
51
49
  "extraThemeNames": z.array(z.string()).optional()
52
50
  })