keycloakify 11.7.4 → 11.8.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 (29) hide show
  1. package/bin/{911.index.js → 297.index.js} +18918 -11359
  2. package/bin/355.index.js +41 -703
  3. package/bin/363.index.js +3 -0
  4. package/bin/369.index.js +968 -0
  5. package/bin/656.index.js +111 -0
  6. package/bin/{288.index.js → 664.index.js} +13 -119
  7. package/bin/780.index.js +9 -7
  8. package/bin/880.index.js +215 -160
  9. package/bin/932.index.js +965 -0
  10. package/bin/97.index.js +2092 -770
  11. package/bin/main.js +52 -24
  12. package/bin/shared/buildContext.d.ts +11 -3
  13. package/package.json +10 -13
  14. package/src/bin/initialize-account-theme/initialize-account-theme.ts +29 -27
  15. package/src/bin/initialize-email-theme.ts +103 -53
  16. package/src/bin/keycloakify/generateResources/generateResources.ts +285 -205
  17. package/src/bin/shared/{initializeSpa/addSyncExtensionsToPostinstallScript.ts → addSyncExtensionsToPostinstallScript.ts} +1 -1
  18. package/src/bin/shared/buildContext.ts +69 -24
  19. package/src/bin/shared/{initializeSpa/initializeSpa.ts → initializeSpa.ts} +3 -3
  20. package/src/bin/sync-extensions/getExtensionModuleFileSourceCodeReadyToBeCopied.ts +6 -0
  21. package/vite-plugin/index.js +48 -20
  22. package/bin/313.index.js +0 -377
  23. package/bin/678.index.js +0 -7565
  24. package/bin/9.index.js +0 -850
  25. package/bin/947.index.js +0 -1565
  26. package/bin/shared/initializeSpa/index.d.ts +0 -1
  27. package/src/bin/shared/initializeSpa/index.ts +0 -1
  28. /package/bin/shared/{initializeSpa/addSyncExtensionsToPostinstallScript.d.ts → addSyncExtensionsToPostinstallScript.d.ts} +0 -0
  29. /package/bin/shared/{initializeSpa/initializeSpa.d.ts → initializeSpa.d.ts} +0 -0
package/bin/main.js CHANGED
@@ -15698,26 +15698,54 @@ function getBuildContext(params) {
15698
15698
  }
15699
15699
  (0,assert/* assert */.h)(false);
15700
15700
  })();
15701
- const implementedThemeTypes = {
15702
- login: {
15703
- isImplemented: external_fs_.existsSync((0,external_path_.join)(themeSrcDirPath, "login"))
15704
- },
15705
- email: {
15706
- isImplemented: external_fs_.existsSync((0,external_path_.join)(themeSrcDirPath, "email"))
15707
- },
15708
- account: (() => {
15709
- if (buildOptions.accountThemeImplementation === "none") {
15710
- return { isImplemented: false };
15711
- }
15712
- return {
15713
- isImplemented: true,
15714
- type: buildOptions.accountThemeImplementation
15715
- };
15716
- })(),
15717
- admin: {
15718
- isImplemented: external_fs_.existsSync((0,external_path_.join)(themeSrcDirPath, "admin"))
15719
- }
15720
- };
15701
+ const implementedThemeTypes = (() => {
15702
+ const getIsNative = (dirPath) => external_fs_.existsSync((0,external_path_.join)(dirPath, "theme.properties"));
15703
+ return {
15704
+ login: (() => {
15705
+ const dirPath = (0,external_path_.join)(themeSrcDirPath, "login");
15706
+ if (!external_fs_.existsSync(dirPath)) {
15707
+ return { isImplemented: false, isImplemented_native: false };
15708
+ }
15709
+ if (getIsNative(dirPath)) {
15710
+ return { isImplemented: false, isImplemented_native: true };
15711
+ }
15712
+ return { isImplemented: true };
15713
+ })(),
15714
+ email: (() => {
15715
+ const dirPath = (0,external_path_.join)(themeSrcDirPath, "email");
15716
+ if (!external_fs_.existsSync(dirPath) || !getIsNative(dirPath)) {
15717
+ return { isImplemented: false, isImplemented_native: false };
15718
+ }
15719
+ return { isImplemented: false, isImplemented_native: true };
15720
+ })(),
15721
+ account: (() => {
15722
+ const dirPath = (0,external_path_.join)(themeSrcDirPath, "account");
15723
+ if (!external_fs_.existsSync(dirPath)) {
15724
+ return { isImplemented: false, isImplemented_native: false };
15725
+ }
15726
+ if (getIsNative(dirPath)) {
15727
+ return { isImplemented: false, isImplemented_native: true };
15728
+ }
15729
+ if (buildOptions.accountThemeImplementation === "none") {
15730
+ return { isImplemented: false, isImplemented_native: false };
15731
+ }
15732
+ return {
15733
+ isImplemented: true,
15734
+ type: buildOptions.accountThemeImplementation
15735
+ };
15736
+ })(),
15737
+ admin: (() => {
15738
+ const dirPath = (0,external_path_.join)(themeSrcDirPath, "admin");
15739
+ if (!external_fs_.existsSync(dirPath)) {
15740
+ return { isImplemented: false, isImplemented_native: false };
15741
+ }
15742
+ if (getIsNative(dirPath)) {
15743
+ return { isImplemented: false, isImplemented_native: true };
15744
+ }
15745
+ return { isImplemented: true };
15746
+ })()
15747
+ };
15748
+ })();
15721
15749
  if (implementedThemeTypes.account.isImplemented &&
15722
15750
  !external_fs_.existsSync((0,external_path_.join)(themeSrcDirPath, "account"))) {
15723
15751
  console.error(source_default().red([
@@ -16201,7 +16229,7 @@ program
16201
16229
  .task({
16202
16230
  skip,
16203
16231
  handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
16204
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(33), __nccwpck_require__.e(911), __nccwpck_require__.e(678), __nccwpck_require__.e(9), __nccwpck_require__.e(947)]).then(__nccwpck_require__.bind(__nccwpck_require__, 32947));
16232
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(33), __nccwpck_require__.e(297), __nccwpck_require__.e(97)]).then(__nccwpck_require__.bind(__nccwpck_require__, 64097));
16205
16233
  await command({
16206
16234
  buildContext: getBuildContext({ projectDirPath }),
16207
16235
  cliCommandOptions: {
@@ -16232,7 +16260,7 @@ program
16232
16260
  .task({
16233
16261
  skip,
16234
16262
  handler: async ({ projectDirPath }) => {
16235
- const { command } = await __nccwpck_require__.e(/* import() */ 97).then(__nccwpck_require__.bind(__nccwpck_require__, 98097));
16263
+ const { command } = await __nccwpck_require__.e(/* import() */ 369).then(__nccwpck_require__.bind(__nccwpck_require__, 98097));
16236
16264
  await command({ buildContext: getBuildContext({ projectDirPath }) });
16237
16265
  }
16238
16266
  });
@@ -16244,7 +16272,7 @@ program
16244
16272
  .task({
16245
16273
  skip,
16246
16274
  handler: async ({ projectDirPath }) => {
16247
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(911), __nccwpck_require__.e(9), __nccwpck_require__.e(313)]).then(__nccwpck_require__.bind(__nccwpck_require__, 16932));
16275
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(664), __nccwpck_require__.e(932)]).then(__nccwpck_require__.bind(__nccwpck_require__, 16932));
16248
16276
  await command({ buildContext: getBuildContext({ projectDirPath }) });
16249
16277
  }
16250
16278
  });
@@ -16268,7 +16296,7 @@ program
16268
16296
  .task({
16269
16297
  skip,
16270
16298
  handler: async ({ projectDirPath }) => {
16271
- const { command } = await __nccwpck_require__.e(/* import() */ 355).then(__nccwpck_require__.bind(__nccwpck_require__, 60355));
16299
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(664), __nccwpck_require__.e(355)]).then(__nccwpck_require__.bind(__nccwpck_require__, 60355));
16272
16300
  await command({ buildContext: getBuildContext({ projectDirPath }) });
16273
16301
  }
16274
16302
  });
@@ -25,19 +25,27 @@ export type BuildContext = {
25
25
  themeSrcDirPath: string;
26
26
  implementedThemeTypes: {
27
27
  login: {
28
- isImplemented: boolean;
28
+ isImplemented: true;
29
+ } | {
30
+ isImplemented: false;
31
+ isImplemented_native: boolean;
29
32
  };
30
33
  email: {
31
- isImplemented: boolean;
34
+ isImplemented: false;
35
+ isImplemented_native: boolean;
32
36
  };
33
37
  account: {
34
38
  isImplemented: false;
39
+ isImplemented_native: boolean;
35
40
  } | {
36
41
  isImplemented: true;
37
42
  type: "Single-Page" | "Multi-Page";
38
43
  };
39
44
  admin: {
40
- isImplemented: boolean;
45
+ isImplemented: true;
46
+ } | {
47
+ isImplemented: false;
48
+ isImplemented_native: boolean;
41
49
  };
42
50
  };
43
51
  packageJsonFilePath: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "11.7.4",
3
+ "version": "11.8.0",
4
4
  "description": "Framework to create custom Keycloak UIs",
5
5
  "repository": {
6
6
  "type": "git",
@@ -681,14 +681,13 @@
681
681
  "src/bin/main.ts",
682
682
  "src/bin/own.ts",
683
683
  "src/bin/shared/KeycloakVersionRange.ts",
684
+ "src/bin/shared/addSyncExtensionsToPostinstallScript.ts",
684
685
  "src/bin/shared/buildContext.ts",
685
686
  "src/bin/shared/constants.ts",
686
687
  "src/bin/shared/customHandler.ts",
687
688
  "src/bin/shared/customHandler_delegate.ts",
688
689
  "src/bin/shared/exitIfUncommittedChanges.ts",
689
- "src/bin/shared/initializeSpa/addSyncExtensionsToPostinstallScript.ts",
690
- "src/bin/shared/initializeSpa/index.ts",
691
- "src/bin/shared/initializeSpa/initializeSpa.ts",
690
+ "src/bin/shared/initializeSpa.ts",
692
691
  "src/bin/shared/metaInfKeycloakThemes.ts",
693
692
  "src/bin/start-keycloak/appBuild.ts",
694
693
  "src/bin/start-keycloak/getSupportedDockerImageTags.ts",
@@ -1053,14 +1052,13 @@
1053
1052
  "bin/keycloakify/replacers/replaceImportsInJsCode/webpack.d.ts",
1054
1053
  "bin/main.d.ts",
1055
1054
  "bin/own.d.ts",
1055
+ "bin/shared/addSyncExtensionsToPostinstallScript.d.ts",
1056
1056
  "bin/shared/buildContext.d.ts",
1057
1057
  "bin/shared/constants.d.ts",
1058
1058
  "bin/shared/customHandler_delegate.d.ts",
1059
1059
  "bin/shared/customHandler.d.ts",
1060
1060
  "bin/shared/exitIfUncommittedChanges.d.ts",
1061
- "bin/shared/initializeSpa/addSyncExtensionsToPostinstallScript.d.ts",
1062
- "bin/shared/initializeSpa/index.d.ts",
1063
- "bin/shared/initializeSpa/initializeSpa.d.ts",
1061
+ "bin/shared/initializeSpa.d.ts",
1064
1062
  "bin/shared/KeycloakVersionRange.d.ts",
1065
1063
  "bin/shared/metaInfKeycloakThemes.d.ts",
1066
1064
  "bin/start-keycloak/appBuild.d.ts",
@@ -1118,27 +1116,26 @@
1118
1116
  "bin/update-kc-gen.d.ts",
1119
1117
  "bin/main.js",
1120
1118
  "bin/266.index.js",
1121
- "bin/288.index.js",
1119
+ "bin/297.index.js",
1122
1120
  "bin/304.index.js",
1123
- "bin/313.index.js",
1124
1121
  "bin/33.index.js",
1125
1122
  "bin/355.index.js",
1126
1123
  "bin/363.index.js",
1124
+ "bin/369.index.js",
1127
1125
  "bin/40.index.js",
1128
1126
  "bin/453.index.js",
1127
+ "bin/656.index.js",
1129
1128
  "bin/658.index.js",
1130
- "bin/678.index.js",
1129
+ "bin/664.index.js",
1131
1130
  "bin/720.index.js",
1132
1131
  "bin/780.index.js",
1133
1132
  "bin/783.index.js",
1134
1133
  "bin/786.index.js",
1135
1134
  "bin/877.index.js",
1136
1135
  "bin/880.index.js",
1137
- "bin/9.index.js",
1138
- "bin/911.index.js",
1139
1136
  "bin/930.index.js",
1137
+ "bin/932.index.js",
1140
1138
  "bin/946.index.js",
1141
- "bin/947.index.js",
1142
1139
  "bin/97.index.js",
1143
1140
  "bin/shared/constants.js",
1144
1141
  "bin/shared/constants.js.map",
@@ -23,22 +23,6 @@ export async function command(params: { buildContext: BuildContext }) {
23
23
 
24
24
  const accountThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "account");
25
25
 
26
- if (
27
- fs.existsSync(accountThemeSrcDirPath) &&
28
- fs.readdirSync(accountThemeSrcDirPath).length > 0
29
- ) {
30
- console.warn(
31
- chalk.red(
32
- `There is already a ${pathRelative(
33
- process.cwd(),
34
- accountThemeSrcDirPath
35
- )} directory in your project. Aborting.`
36
- )
37
- );
38
-
39
- process.exit(-1);
40
- }
41
-
42
26
  exitIfUncommittedChanges({
43
27
  projectDirPath: buildContext.projectDirPath
44
28
  });
@@ -51,17 +35,35 @@ export async function command(params: { buildContext: BuildContext }) {
51
35
 
52
36
  switch (accountThemeType) {
53
37
  case "Multi-Page":
54
- fs.cpSync(
55
- pathJoin(
56
- getThisCodebaseRootDirPath(),
57
- "src",
58
- "bin",
59
- "initialize-account-theme",
60
- "multi-page-boilerplate"
61
- ),
62
- accountThemeSrcDirPath,
63
- { recursive: true }
64
- );
38
+ {
39
+ if (
40
+ fs.existsSync(accountThemeSrcDirPath) &&
41
+ fs.readdirSync(accountThemeSrcDirPath).length > 0
42
+ ) {
43
+ console.warn(
44
+ chalk.red(
45
+ `There is already a ${pathRelative(
46
+ process.cwd(),
47
+ accountThemeSrcDirPath
48
+ )} directory in your project. Aborting.`
49
+ )
50
+ );
51
+
52
+ process.exit(-1);
53
+ }
54
+
55
+ fs.cpSync(
56
+ pathJoin(
57
+ getThisCodebaseRootDirPath(),
58
+ "src",
59
+ "bin",
60
+ "initialize-account-theme",
61
+ "multi-page-boilerplate"
62
+ ),
63
+ accountThemeSrcDirPath,
64
+ { recursive: true }
65
+ );
66
+ }
65
67
  break;
66
68
  case "Single-Page":
67
69
  {
@@ -1,17 +1,24 @@
1
- import { join as pathJoin, relative as pathRelative } from "path";
2
- import { transformCodebase } from "./tools/transformCodebase";
3
1
  import type { BuildContext } from "./shared/buildContext";
4
- import * as fs from "fs";
5
- import { downloadAndExtractArchive } from "./tools/downloadAndExtractArchive";
2
+ import cliSelect from "cli-select";
6
3
  import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
7
- import { assert } from "tsafe/assert";
8
- import { getSupportedDockerImageTags } from "./start-keycloak/getSupportedDockerImageTags";
4
+ import { exitIfUncommittedChanges } from "./shared/exitIfUncommittedChanges";
5
+
6
+ import { dirname as pathDirname, join as pathJoin, relative as pathRelative } from "path";
7
+ import * as fs from "fs";
8
+ import { assert, is, type Equals } from "tsafe/assert";
9
+ import { id } from "tsafe/id";
10
+ import { addSyncExtensionsToPostinstallScript } from "./shared/addSyncExtensionsToPostinstallScript";
11
+ import { getIsPrettierAvailable, runPrettier } from "./tools/runPrettier";
12
+ import { npmInstall } from "./tools/npmInstall";
13
+ import * as child_process from "child_process";
14
+ import { z } from "zod";
15
+ import chalk from "chalk";
9
16
 
10
17
  export async function command(params: { buildContext: BuildContext }) {
11
18
  const { buildContext } = params;
12
19
 
13
20
  const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
14
- commandName: "initialize-email-theme",
21
+ commandName: "initialize-account-theme",
15
22
  buildContext
16
23
  });
17
24
 
@@ -19,6 +26,10 @@ export async function command(params: { buildContext: BuildContext }) {
19
26
  return;
20
27
  }
21
28
 
29
+ exitIfUncommittedChanges({
30
+ projectDirPath: buildContext.projectDirPath
31
+ });
32
+
22
33
  const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
23
34
 
24
35
  if (
@@ -26,71 +37,110 @@ export async function command(params: { buildContext: BuildContext }) {
26
37
  fs.readdirSync(emailThemeSrcDirPath).length > 0
27
38
  ) {
28
39
  console.warn(
29
- `There is already a non empty ${pathRelative(
30
- process.cwd(),
31
- emailThemeSrcDirPath
32
- )} directory in your project. Aborting.`
40
+ chalk.red(
41
+ `There is already a ${pathRelative(
42
+ process.cwd(),
43
+ emailThemeSrcDirPath
44
+ )} directory in your project. Aborting.`
45
+ )
33
46
  );
34
47
 
35
48
  process.exit(-1);
36
49
  }
37
50
 
38
- console.log("Initialize with the base email theme from which version of Keycloak?");
51
+ const { value: emailThemeType } = await cliSelect({
52
+ values: ["native (FreeMarker)" as const, "jsx-email (React)" as const]
53
+ }).catch(() => {
54
+ process.exit(-1);
55
+ });
39
56
 
40
- const { extractedDirPath } = await downloadAndExtractArchive({
41
- url: await (async () => {
42
- const { latestMajorTags } = await getSupportedDockerImageTags({
43
- buildContext
57
+ if (emailThemeType === "jsx-email (React)") {
58
+ console.log(
59
+ [
60
+ "There is currently no automated support for keycloakify-email, it has to be done manually, see documentation:",
61
+ "https://docs.keycloakify.dev/theme-types/email-theme"
62
+ ].join("\n")
63
+ );
64
+
65
+ process.exit(0);
66
+ }
67
+
68
+ const parsedPackageJson = (() => {
69
+ type ParsedPackageJson = {
70
+ scripts?: Record<string, string | undefined>;
71
+ dependencies?: Record<string, string | undefined>;
72
+ devDependencies?: Record<string, string | undefined>;
73
+ };
74
+
75
+ const zParsedPackageJson = (() => {
76
+ type TargetType = ParsedPackageJson;
77
+
78
+ const zTargetType = z.object({
79
+ scripts: z.record(z.union([z.string(), z.undefined()])).optional(),
80
+ dependencies: z.record(z.union([z.string(), z.undefined()])).optional(),
81
+ devDependencies: z.record(z.union([z.string(), z.undefined()])).optional()
44
82
  });
45
83
 
46
- const keycloakVersion = latestMajorTags[0];
84
+ assert<Equals<z.infer<typeof zTargetType>, TargetType>>;
85
+
86
+ return id<z.ZodType<TargetType>>(zTargetType);
87
+ })();
88
+ const parsedPackageJson = JSON.parse(
89
+ fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8")
90
+ );
47
91
 
48
- assert(keycloakVersion !== undefined);
92
+ zParsedPackageJson.parse(parsedPackageJson);
49
93
 
50
- return `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`;
51
- })(),
52
- cacheDirPath: buildContext.cacheDirPath,
53
- fetchOptions: buildContext.fetchOptions,
54
- uniqueIdOfOnArchiveFile: "extractOnlyEmailTheme",
55
- onArchiveFile: async ({ fileRelativePath, writeFile }) => {
56
- const fileRelativePath_target = pathRelative(
57
- pathJoin("theme", "base", "email"),
58
- fileRelativePath
59
- );
94
+ assert(is<ParsedPackageJson>(parsedPackageJson));
60
95
 
61
- if (fileRelativePath_target.startsWith("..")) {
62
- return;
63
- }
96
+ return parsedPackageJson;
97
+ })();
64
98
 
65
- await writeFile({ fileRelativePath: fileRelativePath_target });
66
- }
99
+ addSyncExtensionsToPostinstallScript({
100
+ parsedPackageJson,
101
+ buildContext
67
102
  });
68
103
 
69
- transformCodebase({
70
- srcDirPath: extractedDirPath,
71
- destDirPath: emailThemeSrcDirPath
72
- });
104
+ const moduleName = `@keycloakify/email-native`;
105
+
106
+ const [version] = (
107
+ JSON.parse(
108
+ child_process
109
+ .execSync(`npm show ${moduleName} versions --json`)
110
+ .toString("utf8")
111
+ .trim()
112
+ ) as string[]
113
+ )
114
+ .reverse()
115
+ .filter(version => !version.includes("-"));
116
+
117
+ assert(version !== undefined);
118
+
119
+ (parsedPackageJson.dependencies ??= {})[moduleName] = `~${version}`;
120
+
121
+ if (parsedPackageJson.devDependencies !== undefined) {
122
+ delete parsedPackageJson.devDependencies[moduleName];
123
+ }
73
124
 
74
125
  {
75
- const themePropertyFilePath = pathJoin(emailThemeSrcDirPath, "theme.properties");
126
+ let sourceCode = JSON.stringify(parsedPackageJson, undefined, 2);
127
+
128
+ if (await getIsPrettierAvailable()) {
129
+ sourceCode = await runPrettier({
130
+ sourceCode,
131
+ filePath: buildContext.packageJsonFilePath
132
+ });
133
+ }
76
134
 
77
135
  fs.writeFileSync(
78
- themePropertyFilePath,
79
- Buffer.from(
80
- [
81
- `parent=base`,
82
- fs.readFileSync(themePropertyFilePath).toString("utf8")
83
- ].join("\n"),
84
- "utf8"
85
- )
136
+ buildContext.packageJsonFilePath,
137
+ Buffer.from(sourceCode, "utf8")
86
138
  );
87
139
  }
88
140
 
89
- console.log(
90
- `The \`${pathJoin(
91
- ".",
92
- pathRelative(process.cwd(), emailThemeSrcDirPath)
93
- )}\` directory have been created.`
94
- );
95
- console.log("You can delete any file you don't modify.");
141
+ await npmInstall({
142
+ packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
143
+ });
144
+
145
+ console.log(chalk.green("Email theme initialized."));
96
146
  }