keycloakify 7.7.1 → 7.9.0-rc.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 (66) hide show
  1. package/README.md +4 -1
  2. package/account/kcContext/createGetKcContext.js +3 -6
  3. package/account/kcContext/createGetKcContext.js.map +1 -1
  4. package/account/kcContext/kcContextMocks.js +3 -3
  5. package/account/kcContext/kcContextMocks.js.map +1 -1
  6. package/bin/copy-keycloak-resources-to-public.d.ts +2 -0
  7. package/bin/copy-keycloak-resources-to-public.js +140 -0
  8. package/bin/copy-keycloak-resources-to-public.js.map +1 -0
  9. package/bin/download-builtin-keycloak-theme.js +8 -10
  10. package/bin/download-builtin-keycloak-theme.js.map +1 -1
  11. package/bin/initialize-email-theme.js +5 -2
  12. package/bin/initialize-email-theme.js.map +1 -1
  13. package/bin/keycloakify/BuildOptions.d.ts +1 -2
  14. package/bin/keycloakify/BuildOptions.js +13 -2
  15. package/bin/keycloakify/BuildOptions.js.map +1 -1
  16. package/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.d.ts +7 -0
  17. package/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.js +101 -0
  18. package/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.js.map +1 -0
  19. package/bin/keycloakify/{generateKeycloakThemeResources.d.ts → generateTheme/generateTheme.d.ts} +2 -2
  20. package/bin/keycloakify/{generateKeycloakThemeResources.js → generateTheme/generateTheme.js} +20 -38
  21. package/bin/keycloakify/generateTheme/generateTheme.js.map +1 -0
  22. package/bin/keycloakify/generateTheme/index.d.ts +1 -0
  23. package/bin/keycloakify/generateTheme/index.js +18 -0
  24. package/bin/keycloakify/generateTheme/index.js.map +1 -0
  25. package/bin/keycloakify/keycloakify.js +13 -17
  26. package/bin/keycloakify/keycloakify.js.map +1 -1
  27. package/bin/keycloakify/parsedPackageJson.d.ts +5 -5
  28. package/bin/mockTestingResourcesPath.d.ts +3 -3
  29. package/bin/mockTestingResourcesPath.js +4 -4
  30. package/bin/mockTestingResourcesPath.js.map +1 -1
  31. package/bin/tools/grant-exec-perms.js +2 -1
  32. package/bin/tools/grant-exec-perms.js.map +1 -1
  33. package/bin/tools/walk.js +1 -1
  34. package/lib/usePrepareTemplate.js +27 -15
  35. package/lib/usePrepareTemplate.js.map +1 -1
  36. package/login/kcContext/createGetKcContext.js +3 -6
  37. package/login/kcContext/createGetKcContext.js.map +1 -1
  38. package/login/kcContext/kcContextMocks.js +3 -3
  39. package/login/kcContext/kcContextMocks.js.map +1 -1
  40. package/login/pages/LoginOtp.js +8 -4
  41. package/login/pages/LoginOtp.js.map +1 -1
  42. package/package.json +20 -11
  43. package/src/account/kcContext/createGetKcContext.ts +3 -9
  44. package/src/account/kcContext/kcContextMocks.ts +3 -3
  45. package/src/bin/copy-keycloak-resources-to-public.ts +48 -0
  46. package/src/bin/download-builtin-keycloak-theme.ts +8 -15
  47. package/src/bin/initialize-email-theme.ts +6 -2
  48. package/src/bin/keycloakify/BuildOptions.ts +13 -3
  49. package/src/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.ts +47 -0
  50. package/src/bin/keycloakify/{generateKeycloakThemeResources.ts → generateTheme/generateTheme.ts} +19 -55
  51. package/src/bin/keycloakify/generateTheme/index.ts +1 -0
  52. package/src/bin/keycloakify/keycloakify.ts +6 -10
  53. package/src/bin/mockTestingResourcesPath.ts +3 -3
  54. package/src/lib/usePrepareTemplate.ts +29 -16
  55. package/src/login/kcContext/createGetKcContext.ts +3 -9
  56. package/src/login/kcContext/kcContextMocks.ts +3 -3
  57. package/src/login/pages/LoginOtp.tsx +11 -4
  58. package/src/tools/headInsert.ts +5 -2
  59. package/tools/headInsert.d.ts +4 -1
  60. package/tools/headInsert.js +4 -1
  61. package/tools/headInsert.js.map +1 -1
  62. package/bin/keycloakify/generateKeycloakThemeResources.js.map +0 -1
  63. package/bin/tools/cliOptions.d.ts +0 -5
  64. package/bin/tools/cliOptions.js +0 -16
  65. package/bin/tools/cliOptions.js.map +0 -1
  66. package/src/bin/tools/cliOptions.ts +0 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "7.7.1",
3
+ "version": "7.9.0-rc.0",
4
4
  "description": "Create Keycloak themes using React",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,6 +10,7 @@
10
10
  "types": "index.d.ts",
11
11
  "bin": {
12
12
  "keycloakify": "bin/keycloakify/index.js",
13
+ "copy-keycloak-resources-to-public": "bin/copy-keycloak-resources-to-public.js",
13
14
  "initialize-email-theme": "bin/initialize-email-theme.js",
14
15
  "download-builtin-keycloak-theme": "bin/download-builtin-keycloak-theme.js",
15
16
  "eject-keycloak-page": "bin/eject-keycloak-page.js"
@@ -67,6 +68,7 @@
67
68
  "src/account/pages/Account.tsx",
68
69
  "src/account/pages/PageProps.ts",
69
70
  "src/account/pages/Password.tsx",
71
+ "src/bin/copy-keycloak-resources-to-public.ts",
70
72
  "src/bin/download-builtin-keycloak-theme.ts",
71
73
  "src/bin/eject-keycloak-page.ts",
72
74
  "src/bin/getSrcDirPath.ts",
@@ -78,8 +80,10 @@
78
80
  "src/bin/keycloakify/generateFtl/index.ts",
79
81
  "src/bin/keycloakify/generateFtl/pageId.ts",
80
82
  "src/bin/keycloakify/generateJavaStackFiles.ts",
81
- "src/bin/keycloakify/generateKeycloakThemeResources.ts",
82
83
  "src/bin/keycloakify/generateStartKeycloakTestingContainer.ts",
84
+ "src/bin/keycloakify/generateTheme/downloadKeycloakStaticResources.ts",
85
+ "src/bin/keycloakify/generateTheme/generateTheme.ts",
86
+ "src/bin/keycloakify/generateTheme/index.ts",
83
87
  "src/bin/keycloakify/index.ts",
84
88
  "src/bin/keycloakify/keycloakify.ts",
85
89
  "src/bin/keycloakify/parsedPackageJson.ts",
@@ -89,7 +93,6 @@
89
93
  "src/bin/mockTestingResourcesPath.ts",
90
94
  "src/bin/promptKeycloakVersion.ts",
91
95
  "src/bin/tools/NpmModuleVersion.ts",
92
- "src/bin/tools/cliOptions.ts",
93
96
  "src/bin/tools/crawl.ts",
94
97
  "src/bin/tools/crc32.ts",
95
98
  "src/bin/tools/deflate.ts",
@@ -314,6 +317,9 @@
314
317
  "account/pages/Password.d.ts",
315
318
  "account/pages/Password.js",
316
319
  "account/pages/Password.js.map",
320
+ "bin/copy-keycloak-resources-to-public.d.ts",
321
+ "bin/copy-keycloak-resources-to-public.js",
322
+ "bin/copy-keycloak-resources-to-public.js.map",
317
323
  "bin/download-builtin-keycloak-theme.d.ts",
318
324
  "bin/download-builtin-keycloak-theme.js",
319
325
  "bin/download-builtin-keycloak-theme.js.map",
@@ -345,12 +351,18 @@
345
351
  "bin/keycloakify/generateJavaStackFiles.d.ts",
346
352
  "bin/keycloakify/generateJavaStackFiles.js",
347
353
  "bin/keycloakify/generateJavaStackFiles.js.map",
348
- "bin/keycloakify/generateKeycloakThemeResources.d.ts",
349
- "bin/keycloakify/generateKeycloakThemeResources.js",
350
- "bin/keycloakify/generateKeycloakThemeResources.js.map",
351
354
  "bin/keycloakify/generateStartKeycloakTestingContainer.d.ts",
352
355
  "bin/keycloakify/generateStartKeycloakTestingContainer.js",
353
356
  "bin/keycloakify/generateStartKeycloakTestingContainer.js.map",
357
+ "bin/keycloakify/generateTheme/downloadKeycloakStaticResources.d.ts",
358
+ "bin/keycloakify/generateTheme/downloadKeycloakStaticResources.js",
359
+ "bin/keycloakify/generateTheme/downloadKeycloakStaticResources.js.map",
360
+ "bin/keycloakify/generateTheme/generateTheme.d.ts",
361
+ "bin/keycloakify/generateTheme/generateTheme.js",
362
+ "bin/keycloakify/generateTheme/generateTheme.js.map",
363
+ "bin/keycloakify/generateTheme/index.d.ts",
364
+ "bin/keycloakify/generateTheme/index.js",
365
+ "bin/keycloakify/generateTheme/index.js.map",
354
366
  "bin/keycloakify/index.d.ts",
355
367
  "bin/keycloakify/index.js",
356
368
  "bin/keycloakify/index.js.map",
@@ -378,9 +390,6 @@
378
390
  "bin/tools/NpmModuleVersion.d.ts",
379
391
  "bin/tools/NpmModuleVersion.js",
380
392
  "bin/tools/NpmModuleVersion.js.map",
381
- "bin/tools/cliOptions.d.ts",
382
- "bin/tools/cliOptions.js",
383
- "bin/tools/cliOptions.js.map",
384
393
  "bin/tools/crawl.d.ts",
385
394
  "bin/tools/crawl.js",
386
395
  "bin/tools/crawl.js.map",
@@ -719,7 +728,7 @@
719
728
  "@types/react": "^18.0.35",
720
729
  "@types/react-dom": "^18.0.11",
721
730
  "@types/yauzl": "^2.10.0",
722
- "concurrently": "^7.6.0",
731
+ "concurrently": "^8.0.1",
723
732
  "copyfiles": "^2.4.1",
724
733
  "eslint-plugin-storybook": "^0.6.7",
725
734
  "husky": "^4.3.8",
@@ -733,7 +742,7 @@
733
742
  "storybook-dark-mode": "^1.1.2",
734
743
  "ts-node": "^10.9.1",
735
744
  "tsc-alias": "^1.8.3",
736
- "typescript": "^5.0.4",
745
+ "typescript": "^4.9.1-beta",
737
746
  "vitest": "^0.29.8",
738
747
  "zod-to-json-schema": "^3.20.4"
739
748
  },
@@ -4,7 +4,7 @@ import type { ExtendKcContext } from "./getKcContextFromWindow";
4
4
  import { getKcContextFromWindow } from "./getKcContextFromWindow";
5
5
  import { pathJoin } from "keycloakify/bin/tools/pathJoin";
6
6
  import { pathBasename } from "keycloakify/tools/pathBasename";
7
- import { mockTestingResourcesCommonPath } from "keycloakify/bin/mockTestingResourcesPath";
7
+ import { resourcesCommonDirPathRelativeToPublicDir } from "keycloakify/bin/mockTestingResourcesPath";
8
8
  import { symToStr } from "tsafe/symToStr";
9
9
  import { kcContextMocks, kcContextCommonMock } from "keycloakify/account/kcContext/kcContextMocks";
10
10
  import { id } from "tsafe/id";
@@ -30,13 +30,7 @@ export function createGetKcContext<KcContextExtension extends { pageId: string }
30
30
  if (mockPageId !== undefined && realKcContext === undefined) {
31
31
  //TODO maybe trow if no mock fo custom page
32
32
 
33
- console.log(
34
- [
35
- `%cKeycloakify: ${symToStr({ mockPageId })} set to ${mockPageId}.`,
36
- `If assets are missing make sure you have built your Keycloak theme at least once.`
37
- ].join(" "),
38
- "background: red; color: yellow; font-size: medium"
39
- );
33
+ console.log(`%cKeycloakify: ${symToStr({ mockPageId })} set to ${mockPageId}.`, "background: red; color: yellow; font-size: medium");
40
34
 
41
35
  const kcContextDefaultMock = kcContextMocks.find(({ pageId }) => pageId === mockPageId);
42
36
 
@@ -100,7 +94,7 @@ export function createGetKcContext<KcContextExtension extends { pageId: string }
100
94
  {
101
95
  const { url } = realKcContext;
102
96
 
103
- url.resourcesCommonPath = pathJoin(url.resourcesPath, pathBasename(mockTestingResourcesCommonPath));
97
+ url.resourcesCommonPath = pathJoin(url.resourcesPath, pathBasename(resourcesCommonDirPathRelativeToPublicDir));
104
98
  }
105
99
 
106
100
  return { "kcContext": realKcContext as any };
@@ -1,5 +1,5 @@
1
1
  import "minimal-polyfills/Object.fromEntries";
2
- import { mockTestingResourcesCommonPath, mockTestingResourcesPath } from "keycloakify/bin/mockTestingResourcesPath";
2
+ import { resourcesCommonDirPathRelativeToPublicDir, resourcesDirPathRelativeToPublicDir } from "keycloakify/bin/mockTestingResourcesPath";
3
3
  import { pathJoin } from "keycloakify/bin/tools/pathJoin";
4
4
  import { id } from "tsafe/id";
5
5
  import type { KcContext } from "./KcContext";
@@ -9,8 +9,8 @@ const PUBLIC_URL = process.env["PUBLIC_URL"] ?? "/";
9
9
  export const kcContextCommonMock: KcContext.Common = {
10
10
  "keycloakifyVersion": "0.0.0",
11
11
  "url": {
12
- "resourcesPath": pathJoin(PUBLIC_URL, mockTestingResourcesPath),
13
- "resourcesCommonPath": pathJoin(PUBLIC_URL, mockTestingResourcesCommonPath),
12
+ "resourcesPath": pathJoin(PUBLIC_URL, resourcesDirPathRelativeToPublicDir),
13
+ "resourcesCommonPath": pathJoin(PUBLIC_URL, resourcesCommonDirPathRelativeToPublicDir),
14
14
  "resourceUrl": "#",
15
15
  "accountUrl": "#",
16
16
  "applicationsUrl": "#",
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { downloadKeycloakStaticResources } from "./keycloakify/generateTheme/downloadKeycloakStaticResources";
4
+ import { join as pathJoin, relative as pathRelative } from "path";
5
+ import { basenameOfKeycloakDirInPublicDir } from "./mockTestingResourcesPath";
6
+ import { readBuildOptions } from "./keycloakify/BuildOptions";
7
+ import { themeTypes } from "./keycloakify/generateFtl";
8
+ import * as fs from "fs";
9
+
10
+ (async () => {
11
+ const projectDirPath = process.cwd();
12
+
13
+ const buildOptions = readBuildOptions({
14
+ "processArgv": process.argv.slice(2),
15
+ "projectDirPath": process.cwd()
16
+ });
17
+
18
+ const keycloakDirInPublicDir = pathJoin(process.env["PUBLIC_DIR_PATH"] || pathJoin(projectDirPath, "public"), basenameOfKeycloakDirInPublicDir);
19
+
20
+ if (fs.existsSync(keycloakDirInPublicDir)) {
21
+ console.log(`${pathRelative(projectDirPath, keycloakDirInPublicDir)} already exists.`);
22
+ return;
23
+ }
24
+
25
+ for (const themeType of themeTypes) {
26
+ await downloadKeycloakStaticResources({
27
+ "isSilent": false,
28
+ "keycloakVersion": buildOptions.keycloakVersionDefaultAssets,
29
+ "themeType": themeType,
30
+ "themeDirPath": keycloakDirInPublicDir
31
+ });
32
+ }
33
+
34
+ fs.writeFileSync(
35
+ pathJoin(keycloakDirInPublicDir, "README.txt"),
36
+ Buffer.from(
37
+ // prettier-ignore
38
+ [
39
+ "This is just a test folder that helps develop",
40
+ "the login and register page without having to run a Keycloak container"
41
+ ].join(" ")
42
+ )
43
+ );
44
+
45
+ fs.writeFileSync(pathJoin(keycloakDirInPublicDir, ".gitignore"), Buffer.from("*", "utf8"));
46
+
47
+ console.log(`${pathRelative(projectDirPath, keycloakDirInPublicDir)} directory created.`);
48
+ })();
@@ -2,7 +2,6 @@
2
2
  import { join as pathJoin } from "path";
3
3
  import { downloadAndUnzip } from "./tools/downloadAndUnzip";
4
4
  import { promptKeycloakVersion } from "./promptKeycloakVersion";
5
- import { getCliOptions } from "./tools/cliOptions";
6
5
  import { getLogger } from "./tools/logger";
7
6
  import { readBuildOptions } from "./keycloakify/BuildOptions";
8
7
 
@@ -21,28 +20,22 @@ export async function downloadBuiltinKeycloakTheme(params: { keycloakVersion: st
21
20
  }
22
21
 
23
22
  async function main() {
24
- const { isSilent } = getCliOptions(process.argv.slice(2));
25
- const logger = getLogger({ isSilent });
23
+ const buildOptions = readBuildOptions({
24
+ "projectDirPath": process.cwd(),
25
+ "processArgv": process.argv.slice(2)
26
+ });
27
+
28
+ const logger = getLogger({ "isSilent": buildOptions.isSilent });
26
29
  const { keycloakVersion } = await promptKeycloakVersion();
27
30
 
28
- const destDirPath = pathJoin(
29
- readBuildOptions({
30
- "isSilent": true,
31
- "isExternalAssetsCliParamProvided": false,
32
- "projectDirPath": process.cwd()
33
- }).keycloakifyBuildDirPath,
34
- "src",
35
- "main",
36
- "resources",
37
- "theme"
38
- );
31
+ const destDirPath = pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme");
39
32
 
40
33
  logger.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`);
41
34
 
42
35
  await downloadBuiltinKeycloakTheme({
43
36
  keycloakVersion,
44
37
  destDirPath,
45
- isSilent
38
+ "isSilent": buildOptions.isSilent
46
39
  });
47
40
  }
48
41
 
@@ -4,13 +4,17 @@ import { downloadBuiltinKeycloakTheme } from "./download-builtin-keycloak-theme"
4
4
  import { join as pathJoin, relative as pathRelative } from "path";
5
5
  import { transformCodebase } from "./tools/transformCodebase";
6
6
  import { promptKeycloakVersion } from "./promptKeycloakVersion";
7
+ import { readBuildOptions } from "./keycloakify/BuildOptions";
7
8
  import * as fs from "fs";
8
- import { getCliOptions } from "./tools/cliOptions";
9
9
  import { getLogger } from "./tools/logger";
10
10
  import { getEmailThemeSrcDirPath } from "./getSrcDirPath";
11
11
 
12
12
  export async function main() {
13
- const { isSilent } = getCliOptions(process.argv.slice(2));
13
+ const { isSilent } = readBuildOptions({
14
+ "projectDirPath": process.cwd(),
15
+ "processArgv": process.argv.slice(2)
16
+ });
17
+
14
18
  const logger = getLogger({ isSilent });
15
19
 
16
20
  const { emailThemeSrcDirPath } = getEmailThemeSrcDirPath({
@@ -6,6 +6,7 @@ import { symToStr } from "tsafe/symToStr";
6
6
  import { bundlers, getParsedPackageJson, type Bundler } from "./parsedPackageJson";
7
7
  import * as fs from "fs";
8
8
  import { join as pathJoin, sep as pathSep } from "path";
9
+ import parseArgv from "minimist";
9
10
 
10
11
  /** Consolidated build option gathered form CLI arguments and config in package.json */
11
12
  export type BuildOptions = BuildOptions.Standalone | BuildOptions.ExternalAssets;
@@ -53,8 +54,17 @@ export namespace BuildOptions {
53
54
  }
54
55
  }
55
56
 
56
- export function readBuildOptions(params: { projectDirPath: string; isExternalAssetsCliParamProvided: boolean; isSilent: boolean }): BuildOptions {
57
- const { projectDirPath, isExternalAssetsCliParamProvided, isSilent } = params;
57
+ export function readBuildOptions(params: { projectDirPath: string; processArgv: string[] }): BuildOptions {
58
+ const { projectDirPath, processArgv } = params;
59
+
60
+ const { isExternalAssetsCliParamProvided, isSilentCliParamProvided } = (() => {
61
+ const argv = parseArgv(processArgv);
62
+
63
+ return {
64
+ "isSilentCliParamProvided": typeof argv["silent"] === "boolean" ? argv["silent"] : false,
65
+ "isExternalAssetsCliParamProvided": typeof argv["external-assets"] === "boolean" ? argv["external-assets"] : false
66
+ };
67
+ })();
58
68
 
59
69
  const parsedPackageJson = getParsedPackageJson({ projectDirPath });
60
70
 
@@ -143,7 +153,7 @@ export function readBuildOptions(params: { projectDirPath: string; isExternalAss
143
153
  "extraLoginPages": [...(extraPages ?? []), ...(extraLoginPages ?? [])],
144
154
  extraAccountPages,
145
155
  extraThemeProperties,
146
- isSilent,
156
+ "isSilent": isSilentCliParamProvided,
147
157
  "keycloakVersionDefaultAssets": keycloakVersionDefaultAssets ?? "11.0.3",
148
158
  "reactAppBuildDirPath": (() => {
149
159
  let { reactAppBuildDirPath = undefined } = parsedPackageJson.keycloakify ?? {};
@@ -0,0 +1,47 @@
1
+ import { transformCodebase } from "../../tools/transformCodebase";
2
+ import * as fs from "fs";
3
+ import { join as pathJoin, relative as pathRelative } from "path";
4
+ import type { ThemeType } from "../generateFtl";
5
+ import { downloadBuiltinKeycloakTheme } from "../../download-builtin-keycloak-theme";
6
+ import {
7
+ resourcesCommonDirPathRelativeToPublicDir,
8
+ resourcesDirPathRelativeToPublicDir,
9
+ basenameOfKeycloakDirInPublicDir
10
+ } from "../../mockTestingResourcesPath";
11
+ import * as crypto from "crypto";
12
+
13
+ export async function downloadKeycloakStaticResources(
14
+ // prettier-ignore
15
+ params: {
16
+ themeType: ThemeType;
17
+ themeDirPath: string;
18
+ isSilent: boolean;
19
+ keycloakVersion: string;
20
+ }
21
+ ) {
22
+ const { themeType, isSilent, themeDirPath, keycloakVersion } = params;
23
+
24
+ const tmpDirPath = pathJoin(
25
+ themeDirPath,
26
+ "..",
27
+ `tmp_suLeKsxId_${crypto.createHash("sha256").update(`${themeType}-${keycloakVersion}`).digest("hex").slice(0, 8)}`
28
+ );
29
+
30
+ await downloadBuiltinKeycloakTheme({
31
+ keycloakVersion,
32
+ "destDirPath": tmpDirPath,
33
+ isSilent
34
+ });
35
+
36
+ transformCodebase({
37
+ "srcDirPath": pathJoin(tmpDirPath, "keycloak", themeType, "resources"),
38
+ "destDirPath": pathJoin(themeDirPath, pathRelative(basenameOfKeycloakDirInPublicDir, resourcesDirPathRelativeToPublicDir))
39
+ });
40
+
41
+ transformCodebase({
42
+ "srcDirPath": pathJoin(tmpDirPath, "keycloak", "common", "resources"),
43
+ "destDirPath": pathJoin(themeDirPath, pathRelative(basenameOfKeycloakDirInPublicDir, resourcesCommonDirPathRelativeToPublicDir))
44
+ });
45
+
46
+ fs.rmSync(tmpDirPath, { "recursive": true, "force": true });
47
+ }
@@ -1,14 +1,14 @@
1
- import { transformCodebase } from "../tools/transformCodebase";
1
+ import { transformCodebase } from "../../tools/transformCodebase";
2
2
  import * as fs from "fs";
3
- import { join as pathJoin, basename as pathBasename } from "path";
4
- import { replaceImportsFromStaticInJsCode } from "./replacers/replaceImportsFromStaticInJsCode";
5
- import { replaceImportsInCssCode } from "./replacers/replaceImportsInCssCode";
6
- import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds, themeTypes, type ThemeType } from "./generateFtl";
7
- import { downloadBuiltinKeycloakTheme } from "../download-builtin-keycloak-theme";
8
- import { mockTestingResourcesCommonPath, mockTestingResourcesPath, mockTestingSubDirOfPublicDirBasename } from "../mockTestingResourcesPath";
9
- import { isInside } from "../tools/isInside";
10
- import type { BuildOptions } from "./BuildOptions";
3
+ import { join as pathJoin } from "path";
4
+ import { replaceImportsFromStaticInJsCode } from "../replacers/replaceImportsFromStaticInJsCode";
5
+ import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
6
+ import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds, themeTypes, type ThemeType } from "../generateFtl";
7
+ import { basenameOfKeycloakDirInPublicDir } from "../../mockTestingResourcesPath";
8
+ import { isInside } from "../../tools/isInside";
9
+ import type { BuildOptions } from "../BuildOptions";
11
10
  import { assert } from "tsafe/assert";
11
+ import { downloadKeycloakStaticResources } from "./downloadKeycloakStaticResources";
12
12
 
13
13
  export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
14
14
 
@@ -21,6 +21,7 @@ export namespace BuildOptionsLike {
21
21
  isSilent: boolean;
22
22
  customUserAttributes: string[];
23
23
  themeVersion: string;
24
+ keycloakVersionDefaultAssets: string;
24
25
  };
25
26
 
26
27
  export type Standalone = Common & {
@@ -49,15 +50,14 @@ export namespace BuildOptionsLike {
49
50
 
50
51
  assert<BuildOptions extends BuildOptionsLike ? true : false>();
51
52
 
52
- export async function generateKeycloakThemeResources(params: {
53
+ export async function generateTheme(params: {
53
54
  reactAppBuildDirPath: string;
54
55
  keycloakThemeBuildingDirPath: string;
55
56
  emailThemeSrcDirPath: string | undefined;
56
- keycloakVersion: string;
57
57
  buildOptions: BuildOptionsLike;
58
58
  keycloakifyVersion: string;
59
59
  }): Promise<{ doBundlesEmailTemplate: boolean }> {
60
- const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, keycloakVersion, buildOptions, keycloakifyVersion } = params;
60
+ const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, buildOptions, keycloakifyVersion } = params;
61
61
 
62
62
  const getThemeDirPath = (themeType: ThemeType | "email") =>
63
63
  pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, themeType);
@@ -84,7 +84,7 @@ export async function generateKeycloakThemeResources(params: {
84
84
  if (
85
85
  buildOptions.isStandalone &&
86
86
  isInside({
87
- "dirPath": pathJoin(reactAppBuildDirPath, mockTestingSubDirOfPublicDirBasename),
87
+ "dirPath": pathJoin(reactAppBuildDirPath, basenameOfKeycloakDirInPublicDir),
88
88
  filePath
89
89
  })
90
90
  ) {
@@ -172,48 +172,12 @@ export async function generateKeycloakThemeResources(params: {
172
172
  fs.writeFileSync(pathJoin(themeDirPath, pageId), Buffer.from(ftlCode, "utf8"));
173
173
  });
174
174
 
175
- {
176
- const tmpDirPath = pathJoin(themeDirPath, "..", "tmp_xxKdLpdIdLd");
177
-
178
- await downloadBuiltinKeycloakTheme({
179
- keycloakVersion,
180
- "destDirPath": tmpDirPath,
181
- isSilent: buildOptions.isSilent
182
- });
183
-
184
- const themeResourcesDirPath = pathJoin(themeDirPath, "resources");
185
-
186
- transformCodebase({
187
- "srcDirPath": pathJoin(tmpDirPath, "keycloak", themeType, "resources"),
188
- "destDirPath": themeResourcesDirPath
189
- });
190
-
191
- const reactAppPublicDirPath = pathJoin(reactAppBuildDirPath, "..", "public");
192
-
193
- transformCodebase({
194
- "srcDirPath": pathJoin(tmpDirPath, "keycloak", "common", "resources"),
195
- "destDirPath": pathJoin(themeResourcesDirPath, pathBasename(mockTestingResourcesCommonPath))
196
- });
197
-
198
- transformCodebase({
199
- "srcDirPath": themeResourcesDirPath,
200
- "destDirPath": pathJoin(reactAppPublicDirPath, mockTestingResourcesPath)
201
- });
202
-
203
- const keycloakResourcesWithinPublicDirPath = pathJoin(reactAppPublicDirPath, mockTestingSubDirOfPublicDirBasename);
204
-
205
- fs.writeFileSync(
206
- pathJoin(keycloakResourcesWithinPublicDirPath, "README.txt"),
207
- Buffer.from(
208
- ["This is just a test folder that helps develop", "the login and register page without having to run a Keycloak container"].join(
209
- " "
210
- )
211
- )
212
- );
213
-
214
- fs.writeFileSync(pathJoin(keycloakResourcesWithinPublicDirPath, ".gitignore"), Buffer.from("*", "utf8"));
215
- fs.rmSync(tmpDirPath, { recursive: true, force: true });
216
- }
175
+ await downloadKeycloakStaticResources({
176
+ "isSilent": buildOptions.isSilent,
177
+ "keycloakVersion": buildOptions.keycloakVersionDefaultAssets,
178
+ themeDirPath,
179
+ themeType
180
+ });
217
181
 
218
182
  fs.writeFileSync(
219
183
  pathJoin(themeDirPath, "theme.properties"),
@@ -0,0 +1 @@
1
+ export * from "./generateTheme";
@@ -1,4 +1,4 @@
1
- import { generateKeycloakThemeResources } from "./generateKeycloakThemeResources";
1
+ import { generateTheme } from "./generateTheme";
2
2
  import { generateJavaStackFiles } from "./generateJavaStackFiles";
3
3
  import { join as pathJoin, relative as pathRelative, basename as pathBasename, sep as pathSep } from "path";
4
4
  import * as child_process from "child_process";
@@ -6,7 +6,6 @@ import { generateStartKeycloakTestingContainer } from "./generateStartKeycloakTe
6
6
  import * as fs from "fs";
7
7
  import { readBuildOptions } from "./BuildOptions";
8
8
  import { getLogger } from "../tools/logger";
9
- import { getCliOptions } from "../tools/cliOptions";
10
9
  import jar from "../tools/jar";
11
10
  import { assert } from "tsafe/assert";
12
11
  import { Equals } from "tsafe";
@@ -14,19 +13,17 @@ import { getEmailThemeSrcDirPath } from "../getSrcDirPath";
14
13
  import { getProjectRoot } from "../tools/getProjectRoot";
15
14
 
16
15
  export async function main() {
17
- const { isSilent, hasExternalAssets } = getCliOptions(process.argv.slice(2));
18
- const logger = getLogger({ isSilent });
19
- logger.log("🔏 Building the keycloak theme...⌚");
20
-
21
16
  const projectDirPath = process.cwd();
22
17
 
23
18
  const buildOptions = readBuildOptions({
24
19
  projectDirPath,
25
- "isExternalAssetsCliParamProvided": hasExternalAssets,
26
- "isSilent": isSilent
20
+ "processArgv": process.argv.slice(2)
27
21
  });
28
22
 
29
- const { doBundlesEmailTemplate } = await generateKeycloakThemeResources({
23
+ const logger = getLogger({ "isSilent": buildOptions.isSilent });
24
+ logger.log("🔏 Building the keycloak theme...⌚");
25
+
26
+ const { doBundlesEmailTemplate } = await generateTheme({
30
27
  keycloakThemeBuildingDirPath: buildOptions.keycloakifyBuildDirPath,
31
28
  "emailThemeSrcDirPath": (() => {
32
29
  const { emailThemeSrcDirPath } = getEmailThemeSrcDirPath({ projectDirPath });
@@ -39,7 +36,6 @@ export async function main() {
39
36
  })(),
40
37
  "reactAppBuildDirPath": buildOptions.reactAppBuildDirPath,
41
38
  buildOptions,
42
- "keycloakVersion": buildOptions.keycloakVersionDefaultAssets,
43
39
  "keycloakifyVersion": (() => {
44
40
  const version = JSON.parse(fs.readFileSync(pathJoin(getProjectRoot(), "package.json")).toString("utf8"))["version"];
45
41
 
@@ -1,5 +1,5 @@
1
1
  import { pathJoin } from "./tools/pathJoin";
2
2
 
3
- export const mockTestingSubDirOfPublicDirBasename = "keycloak_static";
4
- export const mockTestingResourcesPath = pathJoin(mockTestingSubDirOfPublicDirBasename, "resources");
5
- export const mockTestingResourcesCommonPath = pathJoin(mockTestingResourcesPath, "resources_common");
3
+ export const basenameOfKeycloakDirInPublicDir = "keycloak-resources";
4
+ export const resourcesDirPathRelativeToPublicDir = pathJoin(basenameOfKeycloakDirInPublicDir, "resources");
5
+ export const resourcesCommonDirPathRelativeToPublicDir = pathJoin(basenameOfKeycloakDirInPublicDir, "resources_common");
@@ -15,7 +15,7 @@ export function usePrepareTemplate(params: {
15
15
  htmlClassName: string | undefined;
16
16
  bodyClassName: string | undefined;
17
17
  }) {
18
- const { doFetchDefaultThemeResources, stylesCommon, styles, url, scripts, htmlClassName, bodyClassName } = params;
18
+ const { doFetchDefaultThemeResources, stylesCommon = [], styles = [], url, scripts = [], htmlClassName, bodyClassName } = params;
19
19
 
20
20
  const [isReady, setReady] = useReducer(() => true, !doFetchDefaultThemeResources);
21
21
 
@@ -26,36 +26,49 @@ export function usePrepareTemplate(params: {
26
26
 
27
27
  let isUnmounted = false;
28
28
 
29
- Promise.all(
29
+ const removeArray: (() => void)[] = [];
30
+
31
+ (async () => {
32
+ const prLoadedArray: Promise<void>[] = [];
33
+
30
34
  [
31
- ...(stylesCommon ?? []).map(relativePath => pathJoin(url.resourcesCommonPath, relativePath)),
32
- ...(styles ?? []).map(relativePath => pathJoin(url.resourcesPath, relativePath))
35
+ ...stylesCommon.map(relativePath => pathJoin(url.resourcesCommonPath, relativePath)),
36
+ ...styles.map(relativePath => pathJoin(url.resourcesPath, relativePath))
33
37
  ]
34
38
  .reverse()
35
- .map(href =>
36
- headInsert({
39
+ .forEach(href => {
40
+ const { prLoaded, remove } = headInsert({
37
41
  "type": "css",
38
- href,
39
- "position": "prepend"
40
- })
41
- )
42
- ).then(() => {
42
+ "position": "prepend",
43
+ href
44
+ });
45
+
46
+ removeArray.push(remove);
47
+
48
+ prLoadedArray.push(prLoaded);
49
+ });
50
+
51
+ await Promise.all(prLoadedArray);
52
+
43
53
  if (isUnmounted) {
44
54
  return;
45
55
  }
46
56
 
47
57
  setReady();
48
- });
58
+ })();
49
59
 
50
- (scripts ?? []).forEach(relativePath =>
51
- headInsert({
60
+ scripts.forEach(relativePath => {
61
+ const { remove } = headInsert({
52
62
  "type": "javascript",
53
63
  "src": pathJoin(url.resourcesPath, relativePath)
54
- })
55
- );
64
+ });
65
+
66
+ removeArray.push(remove);
67
+ });
56
68
 
57
69
  return () => {
58
70
  isUnmounted = true;
71
+ removeArray.forEach(remove => remove());
59
72
  };
60
73
  }, []);
61
74
 
@@ -9,7 +9,7 @@ import type { ExtendKcContext } from "./getKcContextFromWindow";
9
9
  import { getKcContextFromWindow } from "./getKcContextFromWindow";
10
10
  import { pathJoin } from "keycloakify/bin/tools/pathJoin";
11
11
  import { pathBasename } from "keycloakify/tools/pathBasename";
12
- import { mockTestingResourcesCommonPath } from "keycloakify/bin/mockTestingResourcesPath";
12
+ import { resourcesCommonDirPathRelativeToPublicDir } from "keycloakify/bin/mockTestingResourcesPath";
13
13
  import { symToStr } from "tsafe/symToStr";
14
14
  import { loginThemePageIds } from "keycloakify/bin/keycloakify/generateFtl/pageId";
15
15
 
@@ -33,13 +33,7 @@ export function createGetKcContext<KcContextExtension extends { pageId: string }
33
33
  if (mockPageId !== undefined && realKcContext === undefined) {
34
34
  //TODO maybe trow if no mock fo custom page
35
35
 
36
- console.log(
37
- [
38
- `%cKeycloakify: ${symToStr({ mockPageId })} set to ${mockPageId}.`,
39
- `If assets are missing make sure you have built your Keycloak theme at least once.`
40
- ].join(" "),
41
- "background: red; color: yellow; font-size: medium"
42
- );
36
+ console.log(`%cKeycloakify: ${symToStr({ mockPageId })} set to ${mockPageId}.`, "background: red; color: yellow; font-size: medium");
43
37
 
44
38
  const kcContextDefaultMock = kcContextMocks.find(({ pageId }) => pageId === mockPageId);
45
39
 
@@ -158,7 +152,7 @@ export function createGetKcContext<KcContextExtension extends { pageId: string }
158
152
  {
159
153
  const { url } = realKcContext;
160
154
 
161
- url.resourcesCommonPath = pathJoin(url.resourcesPath, pathBasename(mockTestingResourcesCommonPath));
155
+ url.resourcesCommonPath = pathJoin(url.resourcesPath, pathBasename(resourcesCommonDirPathRelativeToPublicDir));
162
156
  }
163
157
 
164
158
  return { "kcContext": realKcContext as any };