keycloakify 10.0.0-rc.17 → 10.0.0-rc.19
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.
- package/PUBLIC_URL.js.map +1 -1
- package/account/Template.js +5 -5
- package/account/Template.js.map +1 -1
- package/account/i18n/i18n.js +37 -29
- package/account/i18n/i18n.js.map +1 -1
- package/account/kcContext/KcContext.js.map +1 -1
- package/account/kcContext/createGetKcContext.js +20 -15
- package/account/kcContext/createGetKcContext.js.map +1 -1
- package/account/kcContext/getKcContext.js.map +1 -1
- package/account/kcContext/getKcContextFromWindow.d.ts +3 -1
- package/account/kcContext/getKcContextFromWindow.js.map +1 -1
- package/account/kcContext/kcContextMocks.js +148 -144
- package/account/kcContext/kcContextMocks.js.map +1 -1
- package/account/lib/useGetClassName.js +14 -14
- package/account/lib/useGetClassName.js.map +1 -1
- package/account/pages/Account.js +1 -1
- package/account/pages/Account.js.map +1 -1
- package/account/pages/Password.js +7 -7
- package/account/pages/Password.js.map +1 -1
- package/account/pages/Totp.js +4 -4
- package/account/pages/Totp.js.map +1 -1
- package/bin/main.js +2265 -2028
- package/bin/shared/constants.d.ts +1 -0
- package/bin/shared/constants.js +4 -3
- package/bin/shared/constants.js.map +1 -1
- package/lib/isStorybook.js +2 -1
- package/lib/isStorybook.js.map +1 -1
- package/lib/useGetClassName.js.map +1 -1
- package/login/Template.js +13 -13
- package/login/Template.js.map +1 -1
- package/login/UserProfileFormFields.js +43 -41
- package/login/UserProfileFormFields.js.map +1 -1
- package/login/i18n/baseMessages/ca.d.ts +1 -1
- package/login/i18n/baseMessages/ca.js +1 -1
- package/login/i18n/baseMessages/el.d.ts +0 -1
- package/login/i18n/baseMessages/el.js +0 -1
- package/login/i18n/baseMessages/el.js.map +1 -1
- package/login/i18n/baseMessages/en.d.ts +1 -1
- package/login/i18n/baseMessages/en.js +1 -1
- package/login/i18n/baseMessages/es.d.ts +1 -1
- package/login/i18n/baseMessages/es.js +1 -1
- package/login/i18n/baseMessages/fa.d.ts +0 -1
- package/login/i18n/baseMessages/fa.js +0 -1
- package/login/i18n/baseMessages/fa.js.map +1 -1
- package/login/i18n/baseMessages/hu.d.ts +1 -1
- package/login/i18n/baseMessages/hu.js +1 -1
- package/login/i18n/baseMessages/index.d.ts +1 -2
- package/login/i18n/baseMessages/zh-CN.d.ts +1 -1
- package/login/i18n/baseMessages/zh-CN.js +1 -1
- package/login/i18n/i18n.js +39 -31
- package/login/i18n/i18n.js.map +1 -1
- package/login/kcContext/KcContext.js.map +1 -1
- package/login/kcContext/createGetKcContext.js +30 -22
- package/login/kcContext/createGetKcContext.js.map +1 -1
- package/login/kcContext/getKcContext.js.map +1 -1
- package/login/kcContext/getKcContextFromWindow.d.ts +3 -1
- package/login/kcContext/getKcContextFromWindow.js.map +1 -1
- package/login/kcContext/kcContextMocks.js +233 -231
- package/login/kcContext/kcContextMocks.js.map +1 -1
- package/login/lib/useDownloadTerms.js.map +1 -1
- package/login/lib/useGetClassName.js +112 -112
- package/login/lib/useGetClassName.js.map +1 -1
- package/login/lib/useUserProfileForm.js +181 -181
- package/login/lib/useUserProfileForm.js.map +1 -1
- package/login/pages/DeleteAccountConfirm.js +5 -1
- package/login/pages/DeleteAccountConfirm.js.map +1 -1
- package/login/pages/FrontchannelLogout.js +1 -1
- package/login/pages/FrontchannelLogout.js.map +1 -1
- package/login/pages/Login.js.map +1 -1
- package/login/pages/LoginRecoveryAuthnCodeConfig.js +3 -3
- package/login/pages/LoginRecoveryAuthnCodeConfig.js.map +1 -1
- package/login/pages/LoginResetPassword.js.map +1 -1
- package/login/pages/LoginUsername.js.map +1 -1
- package/login/pages/WebauthnAuthenticate.js +11 -8
- package/login/pages/WebauthnAuthenticate.js.map +1 -1
- package/login/pages/WebauthnRegister.js +7 -7
- package/login/pages/WebauthnRegister.js.map +1 -1
- package/package.json +232 -226
- package/src/PUBLIC_URL.ts +4 -1
- package/src/account/Template.tsx +5 -5
- package/src/account/TemplateProps.ts +4 -1
- package/src/account/i18n/i18n.tsx +40 -30
- package/src/account/kcContext/KcContext.ts +4 -1
- package/src/account/kcContext/createGetKcContext.ts +48 -22
- package/src/account/kcContext/getKcContext.ts +3 -1
- package/src/account/kcContext/getKcContextFromWindow.ts +6 -2
- package/src/account/kcContext/kcContextMocks.ts +164 -160
- package/src/account/lib/useGetClassName.ts +15 -14
- package/src/account/pages/Account.tsx +2 -2
- package/src/account/pages/Password.tsx +8 -8
- package/src/account/pages/Totp.tsx +4 -6
- package/src/bin/copy-keycloak-resources-to-public.ts +2 -2
- package/src/bin/download-keycloak-default-theme.ts +30 -8
- package/src/bin/eject-page.ts +48 -11
- package/src/bin/initialize-email-theme.ts +25 -17
- package/src/bin/keycloakify/buildJars/buildJar.ts +179 -104
- package/src/bin/keycloakify/buildJars/buildJars.ts +35 -16
- package/src/bin/keycloakify/buildJars/extensionVersions.ts +2 -1
- package/src/bin/keycloakify/buildJars/generatePom.ts +11 -3
- package/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts +33 -8
- package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +20 -2
- package/src/bin/keycloakify/generateFtl/generateFtl.ts +49 -12
- package/src/bin/keycloakify/generateSrcMainResources/bringInAccountV1.ts +29 -18
- package/src/bin/keycloakify/generateSrcMainResources/generateMessageProperties.ts +35 -12
- package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResources.ts +3 -1
- package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForMainTheme.ts +86 -41
- package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForThemeVariant.ts +39 -15
- package/src/bin/keycloakify/generateSrcMainResources/readExtraPageNames.ts +21 -7
- package/src/bin/keycloakify/generateSrcMainResources/readFieldNameUsage.ts +34 -7
- package/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts +19 -5
- package/src/bin/keycloakify/keycloakify.ts +28 -9
- package/src/bin/keycloakify/replacers/replaceImportsInCssCode.ts +24 -5
- package/src/bin/keycloakify/replacers/replaceImportsInInlineCssCode.ts +6 -2
- package/src/bin/keycloakify/replacers/replaceImportsInJsCode/replaceImportsInJsCode.ts +6 -3
- package/src/bin/keycloakify/replacers/replaceImportsInJsCode/vite.ts +24 -6
- package/src/bin/keycloakify/replacers/replaceImportsInJsCode/webpack.ts +49 -11
- package/src/bin/main.ts +78 -41
- package/src/bin/shared/KeycloakVersionRange.ts +3 -1
- package/src/bin/shared/buildOptions.ts +70 -43
- package/src/bin/shared/constants.ts +4 -2
- package/src/bin/shared/copyKeycloakResourcesToPublic.ts +27 -13
- package/src/bin/shared/downloadKeycloakDefaultTheme.ts +161 -218
- package/src/bin/shared/downloadKeycloakStaticResources.ts +25 -21
- package/src/bin/shared/getJarFileBasename.ts +3 -1
- package/src/bin/shared/getThemeSrcDirPath.ts +5 -2
- package/src/bin/shared/metaInfKeycloakThemes.ts +35 -8
- package/src/bin/shared/promptKeycloakVersion.ts +33 -14
- package/src/bin/start-keycloak/appBuild.ts +128 -0
- package/src/bin/start-keycloak/index.ts +1 -0
- package/src/bin/start-keycloak/keycloakifyBuild.ts +41 -0
- package/src/bin/start-keycloak/myrealm-realm-23.json +2142 -0
- package/src/bin/start-keycloak/myrealm-realm-24.json +2318 -0
- package/src/bin/start-keycloak/start-keycloak.ts +469 -0
- package/src/bin/tools/SemVer.ts +32 -13
- package/src/bin/tools/String.prototype.replaceAll.ts +9 -2
- package/src/bin/tools/crawl.ts +4 -1
- package/src/bin/tools/crc32.ts +42 -24
- package/src/bin/tools/downloadAndExtractArchive/downloadAndExtractArchive.ts +262 -0
- package/src/bin/tools/downloadAndExtractArchive/fetchProxyOptions.ts +96 -0
- package/src/bin/tools/downloadAndExtractArchive/index.ts +1 -0
- package/src/bin/tools/extractArchive.ts +132 -0
- package/src/bin/tools/fetchProxyOptions.ts +31 -8
- package/src/bin/tools/getAbsoluteAndInOsFormatPath.ts +10 -2
- package/src/bin/tools/getNpmWorkspaceRootDirPath.ts +18 -5
- package/src/bin/tools/octokit-addons/getLatestsSemVersionedTag.ts +8 -2
- package/src/bin/tools/octokit-addons/listTags.ts +15 -4
- package/src/bin/tools/partitionPromiseSettledResults.ts +12 -3
- package/src/bin/tools/readThisNpmPackageVersion.ts +5 -1
- package/src/bin/tools/transformCodebase.ts +29 -10
- package/src/bin/tools/trimIndent.ts +4 -1
- package/src/lib/isStorybook.ts +3 -1
- package/src/lib/useGetClassName.ts +12 -3
- package/src/login/Template.tsx +14 -14
- package/src/login/TemplateProps.ts +4 -1
- package/src/login/UserProfileFormFields.tsx +44 -42
- package/src/login/i18n/baseMessages/ca.ts +1 -1
- package/src/login/i18n/baseMessages/el.ts +0 -1
- package/src/login/i18n/baseMessages/en.ts +1 -1
- package/src/login/i18n/baseMessages/es.ts +1 -1
- package/src/login/i18n/baseMessages/fa.ts +0 -1
- package/src/login/i18n/baseMessages/hu.ts +1 -1
- package/src/login/i18n/baseMessages/zh-CN.ts +1 -1
- package/src/login/i18n/i18n.tsx +42 -32
- package/src/login/kcContext/KcContext.ts +8 -2
- package/src/login/kcContext/createGetKcContext.ts +84 -37
- package/src/login/kcContext/getKcContext.ts +3 -1
- package/src/login/kcContext/getKcContextFromWindow.ts +6 -2
- package/src/login/kcContext/kcContextMocks.ts +339 -325
- package/src/login/lib/useDownloadTerms.ts +6 -4
- package/src/login/lib/useGetClassName.ts +119 -112
- package/src/login/lib/useUserProfileForm.tsx +219 -205
- package/src/login/pages/DeleteAccountConfirm.tsx +9 -3
- package/src/login/pages/FrontchannelLogout.tsx +1 -1
- package/src/login/pages/Login.tsx +2 -2
- package/src/login/pages/LoginRecoveryAuthnCodeConfig.tsx +3 -3
- package/src/login/pages/LoginResetPassword.tsx +2 -2
- package/src/login/pages/LoginUsername.tsx +2 -2
- package/src/login/pages/WebauthnAuthenticate.tsx +11 -8
- package/src/login/pages/WebauthnRegister.tsx +7 -7
- package/src/tools/AndByDiscriminatingKey.ts +12 -6
- package/src/tools/Array.prototype.every.ts +4 -1
- package/src/tools/LazyOrNot.ts +3 -1
- package/src/tools/clsx.ts +7 -1
- package/src/tools/deepAssign.ts +15 -8
- package/src/tools/deepClone.ts +3 -1
- package/src/tools/formatNumber.ts +4 -1
- package/src/tools/useConstCallback.ts +3 -1
- package/src/tools/useInsertLinkTags.ts +20 -7
- package/src/tools/useInsertScriptTags.ts +7 -2
- package/src/tools/useSetClassName.ts +4 -1
- package/src/vite-plugin/vite-plugin.ts +45 -21
- package/tools/Array.prototype.every.js +2 -1
- package/tools/Array.prototype.every.js.map +1 -1
- package/tools/clsx.js.map +1 -1
- package/tools/deepAssign.js +9 -7
- package/tools/deepAssign.js.map +1 -1
- package/tools/deepClone.js.map +1 -1
- package/tools/formatNumber.js.map +1 -1
- package/tools/useConstCallback.js.map +1 -1
- package/tools/useInsertLinkTags.js +5 -4
- package/tools/useInsertLinkTags.js.map +1 -1
- package/tools/useInsertScriptTags.js +5 -2
- package/tools/useInsertScriptTags.js.map +1 -1
- package/tools/useSetClassName.js.map +1 -1
- package/vite-plugin/index.js +985 -1651
- package/src/bin/shared/downloadAndUnzip.ts +0 -203
- package/src/bin/start-keycloak.ts +0 -309
- package/src/bin/tools/unzip.ts +0 -141
package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForMainTheme.ts
CHANGED
@@ -24,7 +24,10 @@ import { bringInAccountV1 } from "./bringInAccountV1";
|
|
24
24
|
import { getThemeSrcDirPath } from "../../shared/getThemeSrcDirPath";
|
25
25
|
import { rmSync } from "../../tools/fs.rmSync";
|
26
26
|
import { readThisNpmPackageVersion } from "../../tools/readThisNpmPackageVersion";
|
27
|
-
import {
|
27
|
+
import {
|
28
|
+
writeMetaInfKeycloakThemes,
|
29
|
+
type MetaInfKeycloakTheme
|
30
|
+
} from "../../shared/metaInfKeycloakThemes";
|
28
31
|
import { objectEntries } from "tsafe/objectEntries";
|
29
32
|
|
30
33
|
export type BuildOptionsLike = {
|
@@ -43,22 +46,35 @@ export type BuildOptionsLike = {
|
|
43
46
|
|
44
47
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
45
48
|
|
46
|
-
export async function generateSrcMainResourcesForMainTheme(params: {
|
49
|
+
export async function generateSrcMainResourcesForMainTheme(params: {
|
50
|
+
themeName: string;
|
51
|
+
buildOptions: BuildOptionsLike;
|
52
|
+
}): Promise<void> {
|
47
53
|
const { themeName, buildOptions } = params;
|
48
54
|
|
49
|
-
const { themeSrcDirPath } = getThemeSrcDirPath({
|
55
|
+
const { themeSrcDirPath } = getThemeSrcDirPath({
|
56
|
+
reactAppRootDirPath: buildOptions.reactAppRootDirPath
|
57
|
+
});
|
50
58
|
|
51
59
|
const getThemeTypeDirPath = (params: { themeType: ThemeType | "email" }) => {
|
52
60
|
const { themeType } = params;
|
53
|
-
return pathJoin(
|
61
|
+
return pathJoin(
|
62
|
+
buildOptions.keycloakifyBuildDirPath,
|
63
|
+
"src",
|
64
|
+
"main",
|
65
|
+
"resources",
|
66
|
+
"theme",
|
67
|
+
themeName,
|
68
|
+
themeType
|
69
|
+
);
|
54
70
|
};
|
55
71
|
|
56
72
|
const cssGlobalsToDefine: Record<string, string> = {};
|
57
73
|
|
58
74
|
const implementedThemeTypes: Record<ThemeType | "email", boolean> = {
|
59
|
-
|
60
|
-
|
61
|
-
|
75
|
+
login: false,
|
76
|
+
account: false,
|
77
|
+
email: false
|
62
78
|
};
|
63
79
|
|
64
80
|
for (const themeType of ["login", "account"] as const) {
|
@@ -71,18 +87,22 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
71
87
|
const themeTypeDirPath = getThemeTypeDirPath({ themeType });
|
72
88
|
|
73
89
|
apply_replacers_and_move_to_theme_resources: {
|
74
|
-
const destDirPath = pathJoin(
|
90
|
+
const destDirPath = pathJoin(
|
91
|
+
themeTypeDirPath,
|
92
|
+
"resources",
|
93
|
+
basenameOfTheKeycloakifyResourcesDir
|
94
|
+
);
|
75
95
|
|
76
96
|
// NOTE: Prevent accumulation of files in the assets dir, as names are hashed they pile up.
|
77
|
-
rmSync(destDirPath, {
|
97
|
+
rmSync(destDirPath, { recursive: true, force: true });
|
78
98
|
|
79
99
|
if (themeType === "account" && implementedThemeTypes.login) {
|
80
100
|
// NOTE: We prevent doing it twice, it has been done for the login theme.
|
81
101
|
|
82
102
|
transformCodebase({
|
83
|
-
|
103
|
+
srcDirPath: pathJoin(
|
84
104
|
getThemeTypeDirPath({
|
85
|
-
|
105
|
+
themeType: "login"
|
86
106
|
}),
|
87
107
|
"resources",
|
88
108
|
basenameOfTheKeycloakifyResourcesDir
|
@@ -94,14 +114,17 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
94
114
|
}
|
95
115
|
|
96
116
|
transformCodebase({
|
97
|
-
|
117
|
+
srcDirPath: buildOptions.reactAppBuildDirPath,
|
98
118
|
destDirPath,
|
99
|
-
|
119
|
+
transformSourceCode: ({ filePath, sourceCode }) => {
|
100
120
|
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
101
121
|
// This should not happen if users follow the new instruction setup but we keep it for retrocompatibility.
|
102
122
|
if (
|
103
123
|
isInside({
|
104
|
-
|
124
|
+
dirPath: pathJoin(
|
125
|
+
buildOptions.reactAppBuildDirPath,
|
126
|
+
keycloak_resources
|
127
|
+
),
|
105
128
|
filePath
|
106
129
|
})
|
107
130
|
) {
|
@@ -109,39 +132,50 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
109
132
|
}
|
110
133
|
|
111
134
|
if (/\.css?$/i.test(filePath)) {
|
112
|
-
const {
|
113
|
-
|
135
|
+
const {
|
136
|
+
cssGlobalsToDefine: cssGlobalsToDefineForThisFile,
|
137
|
+
fixedCssCode
|
138
|
+
} = replaceImportsInCssCode({
|
139
|
+
cssCode: sourceCode.toString("utf8")
|
114
140
|
});
|
115
141
|
|
116
|
-
Object.entries(cssGlobalsToDefineForThisFile).forEach(
|
117
|
-
|
118
|
-
|
142
|
+
Object.entries(cssGlobalsToDefineForThisFile).forEach(
|
143
|
+
([key, value]) => {
|
144
|
+
cssGlobalsToDefine[key] = value;
|
145
|
+
}
|
146
|
+
);
|
119
147
|
|
120
|
-
return {
|
148
|
+
return {
|
149
|
+
modifiedSourceCode: Buffer.from(fixedCssCode, "utf8")
|
150
|
+
};
|
121
151
|
}
|
122
152
|
|
123
153
|
if (/\.js?$/i.test(filePath)) {
|
124
154
|
const { fixedJsCode } = replaceImportsInJsCode({
|
125
|
-
|
155
|
+
jsCode: sourceCode.toString("utf8"),
|
126
156
|
buildOptions
|
127
157
|
});
|
128
158
|
|
129
|
-
return {
|
159
|
+
return {
|
160
|
+
modifiedSourceCode: Buffer.from(fixedJsCode, "utf8")
|
161
|
+
};
|
130
162
|
}
|
131
163
|
|
132
|
-
return {
|
164
|
+
return { modifiedSourceCode: sourceCode };
|
133
165
|
}
|
134
166
|
});
|
135
167
|
}
|
136
168
|
|
137
169
|
const { generateFtlFilesCode } = generateFtlFilesCodeFactory({
|
138
170
|
themeName,
|
139
|
-
|
171
|
+
indexHtmlCode: fs
|
172
|
+
.readFileSync(pathJoin(buildOptions.reactAppBuildDirPath, "index.html"))
|
173
|
+
.toString("utf8"),
|
140
174
|
cssGlobalsToDefine,
|
141
175
|
buildOptions,
|
142
|
-
|
176
|
+
keycloakifyVersion: readThisNpmPackageVersion(),
|
143
177
|
themeType,
|
144
|
-
|
178
|
+
fieldNames: readFieldNameUsage({
|
145
179
|
themeSrcDirPath,
|
146
180
|
themeType
|
147
181
|
})
|
@@ -163,9 +197,12 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
163
197
|
].forEach(pageId => {
|
164
198
|
const { ftlCode } = generateFtlFilesCode({ pageId });
|
165
199
|
|
166
|
-
fs.mkdirSync(themeTypeDirPath, {
|
200
|
+
fs.mkdirSync(themeTypeDirPath, { recursive: true });
|
167
201
|
|
168
|
-
fs.writeFileSync(
|
202
|
+
fs.writeFileSync(
|
203
|
+
pathJoin(themeTypeDirPath, pageId),
|
204
|
+
Buffer.from(ftlCode, "utf8")
|
205
|
+
);
|
169
206
|
});
|
170
207
|
|
171
208
|
generateMessageProperties({
|
@@ -174,15 +211,23 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
174
211
|
}).forEach(({ languageTag, propertiesFileSource }) => {
|
175
212
|
const messagesDirPath = pathJoin(themeTypeDirPath, "messages");
|
176
213
|
|
177
|
-
fs.mkdirSync(pathJoin(themeTypeDirPath, "messages"), {
|
214
|
+
fs.mkdirSync(pathJoin(themeTypeDirPath, "messages"), {
|
215
|
+
recursive: true
|
216
|
+
});
|
178
217
|
|
179
|
-
const propertiesFilePath = pathJoin(
|
218
|
+
const propertiesFilePath = pathJoin(
|
219
|
+
messagesDirPath,
|
220
|
+
`messages_${languageTag}.properties`
|
221
|
+
);
|
180
222
|
|
181
|
-
fs.writeFileSync(
|
223
|
+
fs.writeFileSync(
|
224
|
+
propertiesFilePath,
|
225
|
+
Buffer.from(propertiesFileSource, "utf8")
|
226
|
+
);
|
182
227
|
});
|
183
228
|
|
184
229
|
await downloadKeycloakStaticResources({
|
185
|
-
|
230
|
+
keycloakVersion: (() => {
|
186
231
|
switch (themeType) {
|
187
232
|
case "account":
|
188
233
|
return lastKeycloakVersionWithAccountV1;
|
@@ -190,7 +235,7 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
190
235
|
return buildOptions.loginThemeResourcesFromKeycloakVersion;
|
191
236
|
}
|
192
237
|
})(),
|
193
|
-
|
238
|
+
themeDirPath: pathResolve(pathJoin(themeTypeDirPath, "..")),
|
194
239
|
themeType,
|
195
240
|
buildOptions
|
196
241
|
});
|
@@ -225,8 +270,8 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
225
270
|
implementedThemeTypes.email = true;
|
226
271
|
|
227
272
|
transformCodebase({
|
228
|
-
|
229
|
-
|
273
|
+
srcDirPath: emailThemeSrcDirPath,
|
274
|
+
destDirPath: getThemeTypeDirPath({ themeType: "email" })
|
230
275
|
});
|
231
276
|
}
|
232
277
|
|
@@ -237,24 +282,24 @@ export async function generateSrcMainResourcesForMainTheme(params: { themeName:
|
|
237
282
|
}
|
238
283
|
|
239
284
|
{
|
240
|
-
const metaInfKeycloakThemes: MetaInfKeycloakTheme = {
|
285
|
+
const metaInfKeycloakThemes: MetaInfKeycloakTheme = { themes: [] };
|
241
286
|
|
242
287
|
metaInfKeycloakThemes.themes.push({
|
243
|
-
|
244
|
-
|
288
|
+
name: themeName,
|
289
|
+
types: objectEntries(implementedThemeTypes)
|
245
290
|
.filter(([, isImplemented]) => isImplemented)
|
246
291
|
.map(([themeType]) => themeType)
|
247
292
|
});
|
248
293
|
|
249
294
|
if (implementedThemeTypes.account) {
|
250
295
|
metaInfKeycloakThemes.themes.push({
|
251
|
-
|
252
|
-
|
296
|
+
name: accountV1ThemeName,
|
297
|
+
types: ["account"]
|
253
298
|
});
|
254
299
|
}
|
255
300
|
|
256
301
|
writeMetaInfKeycloakThemes({
|
257
|
-
|
302
|
+
keycloakifyBuildDirPath: buildOptions.keycloakifyBuildDirPath,
|
258
303
|
metaInfKeycloakThemes
|
259
304
|
});
|
260
305
|
}
|
package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForThemeVariant.ts
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
import { join as pathJoin, extname as pathExtname, sep as pathSep } from "path";
|
2
2
|
import { transformCodebase } from "../../tools/transformCodebase";
|
3
3
|
import type { BuildOptions } from "../../shared/buildOptions";
|
4
|
-
import {
|
4
|
+
import {
|
5
|
+
readMetaInfKeycloakThemes,
|
6
|
+
writeMetaInfKeycloakThemes
|
7
|
+
} from "../../shared/metaInfKeycloakThemes";
|
5
8
|
import { assert } from "tsafe/assert";
|
6
9
|
|
7
10
|
export type BuildOptionsLike = {
|
@@ -10,20 +13,37 @@ export type BuildOptionsLike = {
|
|
10
13
|
|
11
14
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
12
15
|
|
13
|
-
export function generateSrcMainResourcesForThemeVariant(params: {
|
16
|
+
export function generateSrcMainResourcesForThemeVariant(params: {
|
17
|
+
themeName: string;
|
18
|
+
themeVariantName: string;
|
19
|
+
buildOptions: BuildOptionsLike;
|
20
|
+
}) {
|
14
21
|
const { themeName, themeVariantName, buildOptions } = params;
|
15
22
|
|
16
|
-
const mainThemeDirPath = pathJoin(
|
23
|
+
const mainThemeDirPath = pathJoin(
|
24
|
+
buildOptions.keycloakifyBuildDirPath,
|
25
|
+
"src",
|
26
|
+
"main",
|
27
|
+
"resources",
|
28
|
+
"theme",
|
29
|
+
themeName
|
30
|
+
);
|
17
31
|
|
18
32
|
transformCodebase({
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if (
|
33
|
+
srcDirPath: mainThemeDirPath,
|
34
|
+
destDirPath: pathJoin(mainThemeDirPath, "..", themeVariantName),
|
35
|
+
transformSourceCode: ({ fileRelativePath, sourceCode }) => {
|
36
|
+
if (
|
37
|
+
pathExtname(fileRelativePath) === ".ftl" &&
|
38
|
+
fileRelativePath.split(pathSep).length === 2
|
39
|
+
) {
|
23
40
|
const modifiedSourceCode = Buffer.from(
|
24
41
|
Buffer.from(sourceCode)
|
25
42
|
.toString("utf-8")
|
26
|
-
.replace(
|
43
|
+
.replace(
|
44
|
+
`out["themeName"] = "${themeName}";`,
|
45
|
+
`out["themeName"] = "${themeVariantName}";`
|
46
|
+
),
|
27
47
|
"utf8"
|
28
48
|
);
|
29
49
|
|
@@ -32,25 +52,29 @@ export function generateSrcMainResourcesForThemeVariant(params: { themeName: str
|
|
32
52
|
return { modifiedSourceCode };
|
33
53
|
}
|
34
54
|
|
35
|
-
return {
|
55
|
+
return { modifiedSourceCode: sourceCode };
|
36
56
|
}
|
37
57
|
});
|
38
58
|
|
39
59
|
{
|
40
|
-
const updatedMetaInfKeycloakThemes = readMetaInfKeycloakThemes({
|
60
|
+
const updatedMetaInfKeycloakThemes = readMetaInfKeycloakThemes({
|
61
|
+
keycloakifyBuildDirPath: buildOptions.keycloakifyBuildDirPath
|
62
|
+
});
|
41
63
|
|
42
64
|
updatedMetaInfKeycloakThemes.themes.push({
|
43
|
-
|
44
|
-
|
45
|
-
const theme = updatedMetaInfKeycloakThemes.themes.find(
|
65
|
+
name: themeVariantName,
|
66
|
+
types: (() => {
|
67
|
+
const theme = updatedMetaInfKeycloakThemes.themes.find(
|
68
|
+
({ name }) => name === themeName
|
69
|
+
);
|
46
70
|
assert(theme !== undefined);
|
47
71
|
return theme.types;
|
48
72
|
})()
|
49
73
|
});
|
50
74
|
|
51
75
|
writeMetaInfKeycloakThemes({
|
52
|
-
|
53
|
-
|
76
|
+
keycloakifyBuildDirPath: buildOptions.keycloakifyBuildDirPath,
|
77
|
+
metaInfKeycloakThemes: updatedMetaInfKeycloakThemes
|
54
78
|
});
|
55
79
|
}
|
56
80
|
}
|
@@ -3,17 +3,26 @@ import { id } from "tsafe/id";
|
|
3
3
|
import { removeDuplicates } from "evt/tools/reducers/removeDuplicates";
|
4
4
|
import * as fs from "fs";
|
5
5
|
import { join as pathJoin } from "path";
|
6
|
-
import {
|
7
|
-
|
8
|
-
|
6
|
+
import {
|
7
|
+
type ThemeType,
|
8
|
+
accountThemePageIds,
|
9
|
+
loginThemePageIds
|
10
|
+
} from "../../shared/constants";
|
11
|
+
|
12
|
+
export function readExtraPagesNames(params: {
|
13
|
+
themeSrcDirPath: string;
|
14
|
+
themeType: ThemeType;
|
15
|
+
}): string[] {
|
9
16
|
const { themeSrcDirPath, themeType } = params;
|
10
17
|
|
11
18
|
const filePaths = crawl({
|
12
|
-
|
13
|
-
|
19
|
+
dirPath: pathJoin(themeSrcDirPath, themeType),
|
20
|
+
returnedPathsType: "absolute"
|
14
21
|
}).filter(filePath => /\.(ts|tsx|js|jsx)$/.test(filePath));
|
15
22
|
|
16
|
-
const candidateFilePaths = filePaths.filter(filePath =>
|
23
|
+
const candidateFilePaths = filePaths.filter(filePath =>
|
24
|
+
/kcContext\.[^.]+$/.test(filePath)
|
25
|
+
);
|
17
26
|
|
18
27
|
if (candidateFilePaths.length === 0) {
|
19
28
|
candidateFilePaths.push(...filePaths);
|
@@ -24,7 +33,12 @@ export function readExtraPagesNames(params: { themeSrcDirPath: string; themeType
|
|
24
33
|
for (const candidateFilPath of candidateFilePaths) {
|
25
34
|
const rawSourceFile = fs.readFileSync(candidateFilPath).toString("utf8");
|
26
35
|
|
27
|
-
extraPages.push(
|
36
|
+
extraPages.push(
|
37
|
+
...Array.from(
|
38
|
+
rawSourceFile.matchAll(/["']?pageId["']?\s*:\s*["']([^.]+.ftl)["']/g),
|
39
|
+
m => m[1]
|
40
|
+
)
|
41
|
+
);
|
28
42
|
}
|
29
43
|
|
30
44
|
return extraPages.reduce(...removeDuplicates<string>()).filter(pageId => {
|
@@ -5,13 +5,22 @@ import type { ThemeType } from "../../shared/constants";
|
|
5
5
|
import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
|
6
6
|
|
7
7
|
/** Assumes the theme type exists */
|
8
|
-
export function readFieldNameUsage(params: {
|
8
|
+
export function readFieldNameUsage(params: {
|
9
|
+
themeSrcDirPath: string;
|
10
|
+
themeType: ThemeType;
|
11
|
+
}): string[] {
|
9
12
|
const { themeSrcDirPath, themeType } = params;
|
10
13
|
|
11
14
|
const fieldNames = new Set<string>();
|
12
15
|
|
13
|
-
for (const srcDirPath of [
|
14
|
-
|
16
|
+
for (const srcDirPath of [
|
17
|
+
pathJoin(getThisCodebaseRootDirPath(), "src", themeType),
|
18
|
+
pathJoin(themeSrcDirPath, themeType)
|
19
|
+
]) {
|
20
|
+
const filePaths = crawl({
|
21
|
+
dirPath: srcDirPath,
|
22
|
+
returnedPathsType: "absolute"
|
23
|
+
}).filter(filePath => /\.(ts|tsx|js|jsx)$/.test(filePath));
|
15
24
|
|
16
25
|
for (const filePath of filePaths) {
|
17
26
|
const rawSourceFile = fs.readFileSync(filePath).toString("utf8");
|
@@ -20,7 +29,13 @@ export function readFieldNameUsage(params: { themeSrcDirPath: string; themeType:
|
|
20
29
|
continue;
|
21
30
|
}
|
22
31
|
|
23
|
-
for (const functionName of [
|
32
|
+
for (const functionName of [
|
33
|
+
"printIfExists",
|
34
|
+
"existsError",
|
35
|
+
"get",
|
36
|
+
"exists",
|
37
|
+
"getFirstError"
|
38
|
+
] as const) {
|
24
39
|
if (!rawSourceFile.includes(functionName)) {
|
25
40
|
continue;
|
26
41
|
}
|
@@ -40,9 +55,21 @@ export function readFieldNameUsage(params: { themeSrcDirPath: string; themeType:
|
|
40
55
|
return part
|
41
56
|
.split(",")
|
42
57
|
.map(a => a.trim())
|
43
|
-
.filter((...[, i]) =>
|
44
|
-
|
45
|
-
|
58
|
+
.filter((...[, i]) =>
|
59
|
+
functionName !== "printIfExists" ? true : i === 0
|
60
|
+
)
|
61
|
+
.filter(
|
62
|
+
a =>
|
63
|
+
a.startsWith('"') ||
|
64
|
+
a.startsWith("'") ||
|
65
|
+
a.startsWith("`")
|
66
|
+
)
|
67
|
+
.filter(
|
68
|
+
a =>
|
69
|
+
a.endsWith('"') ||
|
70
|
+
a.endsWith("'") ||
|
71
|
+
a.endsWith("`")
|
72
|
+
)
|
46
73
|
.map(a => a.slice(1).slice(0, -1));
|
47
74
|
})
|
48
75
|
.flat()
|
@@ -1,5 +1,9 @@
|
|
1
1
|
import * as fs from "fs";
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
join as pathJoin,
|
4
|
+
relative as pathRelative,
|
5
|
+
basename as pathBasename
|
6
|
+
} from "path";
|
3
7
|
import { assert } from "tsafe/assert";
|
4
8
|
import type { BuildOptions } from "../shared/buildOptions";
|
5
9
|
import { accountV1ThemeName } from "../shared/constants";
|
@@ -27,7 +31,10 @@ export function generateStartKeycloakTestingContainer(params: {
|
|
27
31
|
const themeRelativeDirPath = pathJoin("src", "main", "resources", "theme");
|
28
32
|
|
29
33
|
fs.writeFileSync(
|
30
|
-
pathJoin(
|
34
|
+
pathJoin(
|
35
|
+
buildOptions.keycloakifyBuildDirPath,
|
36
|
+
generateStartKeycloakTestingContainer.basename
|
37
|
+
),
|
31
38
|
Buffer.from(
|
32
39
|
[
|
33
40
|
"#!/usr/bin/env bash",
|
@@ -45,9 +52,16 @@ export function generateStartKeycloakTestingContainer(params: {
|
|
45
52
|
"$(pwd)",
|
46
53
|
pathRelative(buildOptions.keycloakifyBuildDirPath, jarFilePath)
|
47
54
|
)}":"/opt/keycloak/providers/${pathBasename(jarFilePath)}" \\`,
|
48
|
-
[
|
55
|
+
[
|
56
|
+
...(doesImplementAccountTheme ? [accountV1ThemeName] : []),
|
57
|
+
...buildOptions.themeNames
|
58
|
+
].map(
|
49
59
|
themeName =>
|
50
|
-
` -v "${pathJoin(
|
60
|
+
` -v "${pathJoin(
|
61
|
+
"$(pwd)",
|
62
|
+
themeRelativeDirPath,
|
63
|
+
themeName
|
64
|
+
).replace(/\\/g, "/")}":"/opt/keycloak/themes/${themeName}":rw \\`
|
51
65
|
),
|
52
66
|
` -it quay.io/keycloak/keycloak:${keycloakVersion} \\`,
|
53
67
|
` start-dev`,
|
@@ -55,6 +69,6 @@ export function generateStartKeycloakTestingContainer(params: {
|
|
55
69
|
].join("\n"),
|
56
70
|
"utf8"
|
57
71
|
),
|
58
|
-
{
|
72
|
+
{ mode: 0o755 }
|
59
73
|
);
|
60
74
|
}
|
@@ -15,7 +15,9 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
15
15
|
let commandOutput: Buffer | undefined = undefined;
|
16
16
|
|
17
17
|
try {
|
18
|
-
commandOutput = child_process.execSync("mvn --version", {
|
18
|
+
commandOutput = child_process.execSync("mvn --version", {
|
19
|
+
stdio: ["ignore", "pipe", "ignore"]
|
20
|
+
});
|
19
21
|
} catch {}
|
20
22
|
|
21
23
|
if (commandOutput?.toString("utf8").includes("Apache Maven")) {
|
@@ -34,7 +36,11 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
34
36
|
}
|
35
37
|
})();
|
36
38
|
|
37
|
-
console.log(
|
39
|
+
console.log(
|
40
|
+
`${chalk.red("Apache Maven required.")} Install it with \`${chalk.bold(
|
41
|
+
installationCommand
|
42
|
+
)}\` (for example)`
|
43
|
+
);
|
38
44
|
|
39
45
|
process.exit(1);
|
40
46
|
}
|
@@ -46,7 +52,12 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
46
52
|
console.log(
|
47
53
|
[
|
48
54
|
chalk.cyan(`keycloakify v${readThisNpmPackageVersion()}`),
|
49
|
-
chalk.green(
|
55
|
+
chalk.green(
|
56
|
+
`Building the keycloak theme in .${pathSep}${pathRelative(
|
57
|
+
process.cwd(),
|
58
|
+
buildOptions.keycloakifyBuildDirPath
|
59
|
+
)} ...`
|
60
|
+
)
|
50
61
|
].join(" ")
|
51
62
|
);
|
52
63
|
|
@@ -54,10 +65,15 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
54
65
|
|
55
66
|
{
|
56
67
|
if (!fs.existsSync(buildOptions.keycloakifyBuildDirPath)) {
|
57
|
-
fs.mkdirSync(buildOptions.keycloakifyBuildDirPath, {
|
68
|
+
fs.mkdirSync(buildOptions.keycloakifyBuildDirPath, {
|
69
|
+
recursive: true
|
70
|
+
});
|
58
71
|
}
|
59
72
|
|
60
|
-
fs.writeFileSync(
|
73
|
+
fs.writeFileSync(
|
74
|
+
pathJoin(buildOptions.keycloakifyBuildDirPath, ".gitignore"),
|
75
|
+
Buffer.from("*", "utf8")
|
76
|
+
);
|
61
77
|
}
|
62
78
|
|
63
79
|
await generateSrcMainResources({ buildOptions });
|
@@ -68,10 +84,11 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
68
84
|
}
|
69
85
|
|
70
86
|
child_process.execSync("npx vite", {
|
71
|
-
|
72
|
-
|
87
|
+
cwd: buildOptions.reactAppRootDirPath,
|
88
|
+
env: {
|
73
89
|
...process.env,
|
74
|
-
[vitePluginSubScriptEnvNames.runPostBuildScript]:
|
90
|
+
[vitePluginSubScriptEnvNames.runPostBuildScript]:
|
91
|
+
JSON.stringify(buildOptions)
|
75
92
|
}
|
76
93
|
});
|
77
94
|
}
|
@@ -84,5 +101,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
84
101
|
await buildJars({ buildOptions });
|
85
102
|
}
|
86
103
|
|
87
|
-
console.log(
|
104
|
+
console.log(
|
105
|
+
chalk.green(`✓ built in ${((Date.now() - startTime) / 1000).toFixed(2)}s`)
|
106
|
+
);
|
88
107
|
}
|
@@ -18,7 +18,15 @@ export function replaceImportsInCssCode(params: { cssCode: string }): {
|
|
18
18
|
const cssGlobalsToDefine: Record<string, string> = {};
|
19
19
|
|
20
20
|
new Set(cssCode.match(/url\(["']?\/[^/][^)"']+["']?\)[^;}]*?/g) ?? []).forEach(
|
21
|
-
match =>
|
21
|
+
match =>
|
22
|
+
(cssGlobalsToDefine[
|
23
|
+
"url" +
|
24
|
+
crypto
|
25
|
+
.createHash("sha256")
|
26
|
+
.update(match)
|
27
|
+
.digest("hex")
|
28
|
+
.substring(0, 15)
|
29
|
+
] = match)
|
22
30
|
);
|
23
31
|
|
24
32
|
let fixedCssCode = cssCode;
|
@@ -26,26 +34,37 @@ export function replaceImportsInCssCode(params: { cssCode: string }): {
|
|
26
34
|
Object.keys(cssGlobalsToDefine).forEach(
|
27
35
|
cssVariableName =>
|
28
36
|
//NOTE: split/join pattern ~ replace all
|
29
|
-
(fixedCssCode = fixedCssCode
|
37
|
+
(fixedCssCode = fixedCssCode
|
38
|
+
.split(cssGlobalsToDefine[cssVariableName])
|
39
|
+
.join(`var(--${cssVariableName})`))
|
30
40
|
);
|
31
41
|
|
32
42
|
return { fixedCssCode, cssGlobalsToDefine };
|
33
43
|
}
|
34
44
|
|
35
|
-
export function generateCssCodeToDefineGlobals(params: {
|
45
|
+
export function generateCssCodeToDefineGlobals(params: {
|
46
|
+
cssGlobalsToDefine: Record<string, string>;
|
47
|
+
buildOptions: BuildOptionsLike;
|
48
|
+
}): {
|
36
49
|
cssCodeToPrependInHead: string;
|
37
50
|
} {
|
38
51
|
const { cssGlobalsToDefine, buildOptions } = params;
|
39
52
|
|
40
53
|
return {
|
41
|
-
|
54
|
+
cssCodeToPrependInHead: [
|
42
55
|
":root {",
|
43
56
|
...Object.keys(cssGlobalsToDefine)
|
44
57
|
.map(cssVariableName =>
|
45
58
|
[
|
46
59
|
`--${cssVariableName}:`,
|
47
60
|
cssGlobalsToDefine[cssVariableName].replace(
|
48
|
-
new RegExp(
|
61
|
+
new RegExp(
|
62
|
+
`url\\(${(buildOptions.urlPathname ?? "/").replace(
|
63
|
+
/\//g,
|
64
|
+
"\\/"
|
65
|
+
)}`,
|
66
|
+
"g"
|
67
|
+
),
|
49
68
|
`url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/`
|
50
69
|
)
|
51
70
|
].join(" ")
|