keycloakify 10.0.0-rc.63 → 10.0.0-rc.65

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 (34) hide show
  1. package/account/KcContext/KcContext.d.ts +1 -0
  2. package/account/KcContext/KcContext.js.map +1 -1
  3. package/account/KcContext/kcContextMocks.js +2 -1
  4. package/account/KcContext/kcContextMocks.js.map +1 -1
  5. package/account/pages/Totp.js +2 -7
  6. package/account/pages/Totp.js.map +1 -1
  7. package/bin/190.index.js +67 -101
  8. package/bin/{991.index.js → 203.index.js} +40 -19
  9. package/bin/{952.index.js → 363.index.js} +174 -154
  10. package/bin/{214.index.js → 430.index.js} +2 -161
  11. package/bin/526.index.js +130 -90
  12. package/bin/538.index.js +37 -28
  13. package/bin/{98.index.js → 827.index.js} +39 -187
  14. package/bin/{941.index.js → 890.index.js} +159 -2
  15. package/bin/932.index.js +104 -129
  16. package/bin/97.index.js +1 -1
  17. package/bin/main.js +7 -7
  18. package/package.json +9 -8
  19. package/src/account/KcContext/KcContext.ts +1 -0
  20. package/src/account/KcContext/kcContextMocks.ts +2 -1
  21. package/src/account/pages/Totp.tsx +1 -7
  22. package/src/bin/add-story.ts +1 -1
  23. package/src/bin/keycloakify/buildJars/buildJar.ts +24 -27
  24. package/src/bin/keycloakify/buildJars/buildJars.ts +5 -5
  25. package/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl +8 -6
  26. package/src/bin/keycloakify/generateResources/generateResourcesForMainTheme.ts +33 -32
  27. package/src/bin/keycloakify/generateResources/generateResourcesForThemeVariant.ts +22 -26
  28. package/src/bin/shared/downloadKeycloakDefaultTheme.ts +135 -108
  29. package/src/bin/shared/getImplementedThemeTypes.ts +38 -0
  30. package/src/bin/shared/getThemeSrcDirPath.ts +44 -32
  31. package/src/bin/shared/metaInfKeycloakThemes.ts +16 -60
  32. package/src/bin/start-keycloak/keycloakifyBuild.ts +1 -1
  33. package/src/bin/start-keycloak/start-keycloak.ts +35 -70
  34. package/vite-plugin/index.js +1917 -100
@@ -0,0 +1,38 @@
1
+ import { join as pathJoin } from "path";
2
+ import { objectFromEntries } from "tsafe/objectFromEntries";
3
+ import * as fs from "fs";
4
+ import { type ThemeType } from "./constants";
5
+ import { getThemeSrcDirPath } from "./getThemeSrcDirPath";
6
+
7
+ type ImplementedThemeTypes = Readonly<Record<ThemeType | "email", boolean>>;
8
+
9
+ let cache:
10
+ | { projectDirPath: string; implementedThemeTypes: ImplementedThemeTypes }
11
+ | undefined;
12
+
13
+ export function getImplementedThemeTypes(params: { projectDirPath: string }) {
14
+ const { projectDirPath } = params;
15
+
16
+ if (cache !== undefined && cache.projectDirPath === projectDirPath) {
17
+ const { implementedThemeTypes } = cache;
18
+ return { implementedThemeTypes };
19
+ }
20
+
21
+ cache = undefined;
22
+
23
+ const { themeSrcDirPath } = getThemeSrcDirPath({
24
+ projectDirPath
25
+ });
26
+
27
+ const implementedThemeTypes: Readonly<Record<ThemeType | "email", boolean>> =
28
+ objectFromEntries(
29
+ (["login", "account", "email"] as const).map(themeType => [
30
+ themeType,
31
+ fs.existsSync(pathJoin(themeSrcDirPath, themeType))
32
+ ])
33
+ );
34
+
35
+ cache = { projectDirPath, implementedThemeTypes };
36
+
37
+ return { implementedThemeTypes };
38
+ }
@@ -3,48 +3,60 @@ import { exclude } from "tsafe";
3
3
  import { crawl } from "../tools/crawl";
4
4
  import { join as pathJoin } from "path";
5
5
  import { themeTypes } from "./constants";
6
+ import chalk from "chalk";
6
7
 
7
- const themeSrcDirBasenames = ["keycloak-theme", "keycloak_theme"];
8
+ let cache: { projectDirPath: string; themeSrcDirPath: string } | undefined = undefined;
8
9
 
9
10
  /** Can't catch error, if the directory isn't found, this function will just exit the process with an error message. */
10
11
  export function getThemeSrcDirPath(params: { projectDirPath: string }) {
11
12
  const { projectDirPath } = params;
12
13
 
13
- const srcDirPath = pathJoin(projectDirPath, "src");
14
-
15
- const themeSrcDirPath: string | undefined = crawl({
16
- dirPath: srcDirPath,
17
- returnedPathsType: "relative to dirPath"
18
- })
19
- .map(fileRelativePath => {
20
- for (const themeSrcDirBasename of themeSrcDirBasenames) {
21
- const split = fileRelativePath.split(themeSrcDirBasename);
22
- if (split.length === 2) {
23
- return pathJoin(srcDirPath, split[0] + themeSrcDirBasename);
24
- }
25
- }
26
- return undefined;
27
- })
28
- .filter(exclude(undefined))[0];
29
-
30
- if (themeSrcDirPath !== undefined) {
14
+ if (cache !== undefined && cache.projectDirPath === projectDirPath) {
15
+ const { themeSrcDirPath } = cache;
31
16
  return { themeSrcDirPath };
32
17
  }
33
18
 
34
- for (const themeType of [...themeTypes, "email"]) {
35
- if (!fs.existsSync(pathJoin(srcDirPath, themeType))) {
36
- continue;
19
+ cache = undefined;
20
+
21
+ const { themeSrcDirPath } = (() => {
22
+ const srcDirPath = pathJoin(projectDirPath, "src");
23
+
24
+ const themeSrcDirPath: string | undefined = crawl({
25
+ dirPath: srcDirPath,
26
+ returnedPathsType: "relative to dirPath"
27
+ })
28
+ .map(fileRelativePath => {
29
+ for (const themeSrcDirBasename of themeSrcDirBasenames) {
30
+ const split = fileRelativePath.split(themeSrcDirBasename);
31
+ if (split.length === 2) {
32
+ return pathJoin(srcDirPath, split[0] + themeSrcDirBasename);
33
+ }
34
+ }
35
+ return undefined;
36
+ })
37
+ .filter(exclude(undefined))[0];
38
+
39
+ if (themeSrcDirPath !== undefined) {
40
+ return { themeSrcDirPath };
41
+ }
42
+
43
+ for (const themeType of [...themeTypes, "email"]) {
44
+ if (!fs.existsSync(pathJoin(srcDirPath, themeType))) {
45
+ continue;
46
+ }
47
+ return { themeSrcDirPath: srcDirPath };
37
48
  }
38
- return { themeSrcDirPath: srcDirPath };
39
- }
40
49
 
41
- console.error(
42
- [
43
- "Can't locate your theme source directory. It should be either: ",
44
- "src/ or src/keycloak-theme or src/keycloak_theme.",
45
- "Example in the starter: https://github.com/keycloakify/keycloakify-starter/tree/main/src/keycloak-theme"
46
- ].join("\n")
47
- );
50
+ console.log(
51
+ chalk.red("Can't locate your theme source directory. It should be either: ")
52
+ );
48
53
 
49
- process.exit(-1);
54
+ process.exit(-1);
55
+ })();
56
+
57
+ cache = { projectDirPath, themeSrcDirPath };
58
+
59
+ return { themeSrcDirPath };
50
60
  }
61
+
62
+ const themeSrcDirBasenames = ["keycloak-theme", "keycloak_theme"];
@@ -1,84 +1,40 @@
1
1
  import { join as pathJoin, dirname as pathDirname } from "path";
2
2
  import type { ThemeType } from "./constants";
3
3
  import * as fs from "fs";
4
- import { assert } from "tsafe/assert";
5
- import { extractArchive } from "../tools/extractArchive";
6
4
 
7
5
  export type MetaInfKeycloakTheme = {
8
6
  themes: { name: string; types: (ThemeType | "email")[] }[];
9
7
  };
10
8
 
11
- export function getMetaInfKeycloakThemesJsonFilePath(params: {
12
- resourcesDirPath: string;
13
- }) {
14
- const { resourcesDirPath } = params;
15
-
16
- return pathJoin(
17
- resourcesDirPath === "." ? "" : resourcesDirPath,
18
- "META-INF",
19
- "keycloak-themes.json"
20
- );
21
- }
22
-
23
- export function readMetaInfKeycloakThemes_fromResourcesDirPath(params: {
9
+ export function writeMetaInfKeycloakThemes(params: {
24
10
  resourcesDirPath: string;
11
+ getNewMetaInfKeycloakTheme: (params: {
12
+ metaInfKeycloakTheme: MetaInfKeycloakTheme | undefined;
13
+ }) => MetaInfKeycloakTheme;
25
14
  }) {
26
- const { resourcesDirPath } = params;
27
-
28
- return JSON.parse(
29
- fs
30
- .readFileSync(
31
- getMetaInfKeycloakThemesJsonFilePath({
32
- resourcesDirPath
33
- })
34
- )
35
- .toString("utf8")
36
- ) as MetaInfKeycloakTheme;
37
- }
15
+ const { resourcesDirPath, getNewMetaInfKeycloakTheme } = params;
38
16
 
39
- export async function readMetaInfKeycloakThemes_fromJar(params: {
40
- jarFilePath: string;
41
- }): Promise<MetaInfKeycloakTheme> {
42
- const { jarFilePath } = params;
43
- let metaInfKeycloakThemes: MetaInfKeycloakTheme | undefined = undefined;
17
+ const filePath = pathJoin(resourcesDirPath, "META-INF", "keycloak-themes.json");
44
18
 
45
- await extractArchive({
46
- archiveFilePath: jarFilePath,
47
- onArchiveFile: async ({ relativeFilePathInArchive, readFile, earlyExit }) => {
48
- if (
49
- relativeFilePathInArchive ===
50
- getMetaInfKeycloakThemesJsonFilePath({ resourcesDirPath: "." })
51
- ) {
52
- metaInfKeycloakThemes = JSON.parse((await readFile()).toString("utf8"));
53
- earlyExit();
54
- }
55
- }
56
- });
57
-
58
- assert(metaInfKeycloakThemes !== undefined);
59
-
60
- return metaInfKeycloakThemes;
61
- }
62
-
63
- export function writeMetaInfKeycloakThemes(params: {
64
- resourcesDirPath: string;
65
- metaInfKeycloakThemes: MetaInfKeycloakTheme;
66
- }) {
67
- const { resourcesDirPath, metaInfKeycloakThemes } = params;
19
+ const currentMetaInfKeycloakTheme = !fs.existsSync(filePath)
20
+ ? undefined
21
+ : (JSON.parse(
22
+ fs.readFileSync(filePath).toString("utf8")
23
+ ) as MetaInfKeycloakTheme);
68
24
 
69
- const metaInfKeycloakThemesJsonPath = getMetaInfKeycloakThemesJsonFilePath({
70
- resourcesDirPath
25
+ const newMetaInfKeycloakThemes = getNewMetaInfKeycloakTheme({
26
+ metaInfKeycloakTheme: currentMetaInfKeycloakTheme
71
27
  });
72
28
 
73
29
  {
74
- const dirPath = pathDirname(metaInfKeycloakThemesJsonPath);
30
+ const dirPath = pathDirname(filePath);
75
31
  if (!fs.existsSync(dirPath)) {
76
32
  fs.mkdirSync(dirPath, { recursive: true });
77
33
  }
78
34
  }
79
35
 
80
36
  fs.writeFileSync(
81
- metaInfKeycloakThemesJsonPath,
82
- Buffer.from(JSON.stringify(metaInfKeycloakThemes, null, 2), "utf8")
37
+ filePath,
38
+ Buffer.from(JSON.stringify(newMetaInfKeycloakThemes, null, 2), "utf8")
83
39
  );
84
40
  }
@@ -14,7 +14,7 @@ export type BuildContextLike = {
14
14
  assert<BuildContext extends BuildContextLike ? true : false>();
15
15
 
16
16
  export async function keycloakifyBuild(params: {
17
- onlyBuildJarFileBasename: string | undefined;
17
+ onlyBuildJarFileBasename: string;
18
18
  buildContext: BuildContextLike;
19
19
  }): Promise<{ isKeycloakifyBuildSuccess: boolean }> {
20
20
  const { buildContext, onlyBuildJarFileBasename } = params;
@@ -2,7 +2,7 @@ import { getBuildContext } from "../shared/buildContext";
2
2
  import { exclude } from "tsafe/exclude";
3
3
  import type { CliCommandOptions as CliCommandOptions_common } from "../main";
4
4
  import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
5
- import { readMetaInfKeycloakThemes_fromJar } from "../shared/metaInfKeycloakThemes";
5
+ import { getImplementedThemeTypes } from "../shared/getImplementedThemeTypes";
6
6
  import { accountV1ThemeName, containerName } from "../shared/constants";
7
7
  import { SemVer } from "../tools/SemVer";
8
8
  import type { KeycloakVersionRange } from "../shared/KeycloakVersionRange";
@@ -91,66 +91,8 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
91
91
 
92
92
  const buildContext = getBuildContext({ cliCommandOptions });
93
93
 
94
- {
95
- const { isAppBuildSuccess } = await appBuild({
96
- buildContext
97
- });
98
-
99
- if (!isAppBuildSuccess) {
100
- console.log(
101
- chalk.red(
102
- `App build failed, exiting. Try running 'yarn build-keycloak-theme' and see what's wrong.`
103
- )
104
- );
105
- process.exit(1);
106
- }
107
-
108
- const { isKeycloakifyBuildSuccess } = await keycloakifyBuild({
109
- onlyBuildJarFileBasename: undefined,
110
- buildContext
111
- });
112
-
113
- if (!isKeycloakifyBuildSuccess) {
114
- console.log(
115
- chalk.red(
116
- `Keycloakify build failed, exiting. Try running 'yarn build-keycloak-theme' and see what's wrong.`
117
- )
118
- );
119
- process.exit(1);
120
- }
121
- }
122
-
123
- const { doesImplementAccountTheme } = await (async () => {
124
- const latestJarFilePath = fs
125
- .readdirSync(buildContext.keycloakifyBuildDirPath)
126
- .filter(fileBasename => fileBasename.endsWith(".jar"))
127
- .map(fileBasename =>
128
- pathJoin(buildContext.keycloakifyBuildDirPath, fileBasename)
129
- )
130
- .sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs)[0];
131
-
132
- assert(latestJarFilePath !== undefined);
133
-
134
- const metaInfKeycloakThemes = await readMetaInfKeycloakThemes_fromJar({
135
- jarFilePath: latestJarFilePath
136
- });
137
-
138
- const mainThemeEntry = metaInfKeycloakThemes.themes.find(
139
- ({ name }) => name === buildContext.themeNames[0]
140
- );
141
-
142
- assert(mainThemeEntry !== undefined);
143
-
144
- const doesImplementAccountTheme = mainThemeEntry.types.includes("account");
145
-
146
- return { doesImplementAccountTheme };
147
- })();
148
-
149
94
  const { keycloakVersion, keycloakMajorNumber: keycloakMajorVersionNumber } =
150
- await (async function getKeycloakMajor(): Promise<{
151
- keycloakVersion: string;
152
- keycloakMajorNumber: number;
153
- }> {
95
+ await (async () => {
154
96
  if (cliCommandOptions.keycloakVersion !== undefined) {
155
97
  return {
156
98
  keycloakVersion: cliCommandOptions.keycloakVersion,
@@ -173,20 +115,14 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
173
115
 
174
116
  const keycloakMajorNumber = SemVer.parse(keycloakVersion).major;
175
117
 
176
- if (doesImplementAccountTheme && keycloakMajorNumber === 22) {
177
- console.log(
178
- [
179
- "Unfortunately, Keycloakify themes that implements an account theme do not work on Keycloak 22",
180
- "Please select any other Keycloak version"
181
- ].join(" ")
182
- );
183
- return getKeycloakMajor();
184
- }
185
-
186
118
  return { keycloakVersion, keycloakMajorNumber };
187
119
  })();
188
120
 
189
121
  const keycloakVersionRange: KeycloakVersionRange = (() => {
122
+ const doesImplementAccountTheme = getImplementedThemeTypes({
123
+ projectDirPath: buildContext.projectDirPath
124
+ }).implementedThemeTypes.account;
125
+
190
126
  if (doesImplementAccountTheme) {
191
127
  const keycloakVersionRange = (() => {
192
128
  if (keycloakMajorVersionNumber <= 21) {
@@ -233,6 +169,35 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
233
169
 
234
170
  const { jarFileBasename } = getJarFileBasename({ keycloakVersionRange });
235
171
 
172
+ {
173
+ const { isAppBuildSuccess } = await appBuild({
174
+ buildContext
175
+ });
176
+
177
+ if (!isAppBuildSuccess) {
178
+ console.log(
179
+ chalk.red(
180
+ `App build failed, exiting. Try running 'npm run build-keycloak-theme' and see what's wrong.`
181
+ )
182
+ );
183
+ process.exit(1);
184
+ }
185
+
186
+ const { isKeycloakifyBuildSuccess } = await keycloakifyBuild({
187
+ onlyBuildJarFileBasename: jarFileBasename,
188
+ buildContext
189
+ });
190
+
191
+ if (!isKeycloakifyBuildSuccess) {
192
+ console.log(
193
+ chalk.red(
194
+ `Keycloakify build failed, exiting. Try running 'npm run build-keycloak-theme' and see what's wrong.`
195
+ )
196
+ );
197
+ process.exit(1);
198
+ }
199
+ }
200
+
236
201
  console.log(`Using Keycloak ${chalk.bold(jarFileBasename)}`);
237
202
 
238
203
  const realmJsonFilePath = await (async () => {