keycloakify 10.0.0-rc.70 → 10.0.0-rc.71

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=KeycloakVersionRange.js.map
@@ -0,0 +1,488 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { parse as urlParse } from "url";
13
+ import { join as pathJoin } from "path";
14
+ import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
15
+ import { getNpmWorkspaceRootDirPath } from "../tools/getNpmWorkspaceRootDirPath";
16
+ import { z } from "zod";
17
+ import * as fs from "fs";
18
+ import { assert } from "tsafe/assert";
19
+ import * as child_process from "child_process";
20
+ import { vitePluginSubScriptEnvNames, buildForKeycloakMajorVersionEnvName } from "./constants";
21
+ import { exclude } from "tsafe";
22
+ import { crawl } from "../tools/crawl";
23
+ import { themeTypes } from "./constants";
24
+ import { objectFromEntries } from "tsafe/objectFromEntries";
25
+ import { objectEntries } from "tsafe/objectEntries";
26
+ import { id } from "tsafe/id";
27
+ import { symToStr } from "tsafe/symToStr";
28
+ import chalk from "chalk";
29
+ export function getBuildContext(params) {
30
+ var _a, _b, _c, _d, _e, _f;
31
+ const { cliCommandOptions } = params;
32
+ const projectDirPath = (() => {
33
+ if (cliCommandOptions.projectDirPath === undefined) {
34
+ return process.cwd();
35
+ }
36
+ return getAbsoluteAndInOsFormatPath({
37
+ pathIsh: cliCommandOptions.projectDirPath,
38
+ cwd: process.cwd()
39
+ });
40
+ })();
41
+ const { resolvedViteConfig } = (() => {
42
+ if (fs
43
+ .readdirSync(projectDirPath)
44
+ .find(fileBasename => fileBasename.startsWith("vite.config")) ===
45
+ undefined) {
46
+ return { resolvedViteConfig: undefined };
47
+ }
48
+ const output = child_process
49
+ .execSync("npx vite", {
50
+ cwd: projectDirPath,
51
+ env: Object.assign(Object.assign({}, process.env), { [vitePluginSubScriptEnvNames.resolveViteConfig]: "true" })
52
+ })
53
+ .toString("utf8");
54
+ assert(output.includes(vitePluginSubScriptEnvNames.resolveViteConfig), "Seems like the Keycloakify's Vite plugin is not installed.");
55
+ const resolvedViteConfigStr = output
56
+ .split(vitePluginSubScriptEnvNames.resolveViteConfig)
57
+ .reverse()[0];
58
+ const resolvedViteConfig = JSON.parse(resolvedViteConfigStr);
59
+ return { resolvedViteConfig };
60
+ })();
61
+ const parsedPackageJson = (() => {
62
+ const zParsedPackageJson = z.object({
63
+ name: z.string(),
64
+ version: z.string().optional(),
65
+ homepage: z.string().optional(),
66
+ keycloakify: id((() => {
67
+ const zBuildOptions_packageJson = z.object({
68
+ extraThemeProperties: z.array(z.string()).optional(),
69
+ artifactId: z.string().optional(),
70
+ groupId: z.string().optional(),
71
+ loginThemeResourcesFromKeycloakVersion: z.string().optional(),
72
+ projectBuildDirPath: z.string().optional(),
73
+ keycloakifyBuildDirPath: z.string().optional(),
74
+ kcContextExclusionsFtl: z.string().optional(),
75
+ environmentVariables: z
76
+ .array(z.object({
77
+ name: z.string(),
78
+ default: z.string()
79
+ }))
80
+ .optional(),
81
+ themeName: z.union([z.string(), z.array(z.string())]).optional(),
82
+ themeVersion: z.string().optional(),
83
+ staticDirPathInProjectBuildDirPath: z.string().optional(),
84
+ publicDirPath: z.string().optional(),
85
+ keycloakVersionTargets: id((() => {
86
+ const zKeycloakVersionTargets = z.union([
87
+ z.object({
88
+ hasAccountTheme: z.literal(true),
89
+ "21-and-below": z.union([
90
+ z.boolean(),
91
+ z.string()
92
+ ]),
93
+ "23": z.union([z.boolean(), z.string()]),
94
+ "24": z.union([z.boolean(), z.string()]),
95
+ "25-and-above": z.union([z.boolean(), z.string()])
96
+ }),
97
+ z.object({
98
+ hasAccountTheme: z.literal(false),
99
+ "21-and-below": z.union([
100
+ z.boolean(),
101
+ z.string()
102
+ ]),
103
+ "22-and-above": z.union([z.boolean(), z.string()])
104
+ })
105
+ ]);
106
+ {
107
+ assert();
108
+ }
109
+ return zKeycloakVersionTargets;
110
+ })()).optional()
111
+ });
112
+ {
113
+ assert();
114
+ }
115
+ return zBuildOptions_packageJson;
116
+ })()).optional()
117
+ });
118
+ {
119
+ assert();
120
+ }
121
+ return zParsedPackageJson.parse(JSON.parse(fs.readFileSync(pathJoin(projectDirPath, "package.json")).toString("utf8")));
122
+ })();
123
+ const buildOptions = Object.assign(Object.assign({}, parsedPackageJson.keycloakify), resolvedViteConfig === null || resolvedViteConfig === void 0 ? void 0 : resolvedViteConfig.buildOptions);
124
+ const { themeSrcDirPath } = (() => {
125
+ const srcDirPath = pathJoin(projectDirPath, "src");
126
+ const themeSrcDirPath = crawl({
127
+ dirPath: srcDirPath,
128
+ returnedPathsType: "relative to dirPath"
129
+ })
130
+ .map(fileRelativePath => {
131
+ for (const themeSrcDirBasename of ["keycloak-theme", "keycloak_theme"]) {
132
+ const split = fileRelativePath.split(themeSrcDirBasename);
133
+ if (split.length === 2) {
134
+ return pathJoin(srcDirPath, split[0] + themeSrcDirBasename);
135
+ }
136
+ }
137
+ return undefined;
138
+ })
139
+ .filter(exclude(undefined))[0];
140
+ if (themeSrcDirPath !== undefined) {
141
+ return { themeSrcDirPath };
142
+ }
143
+ for (const themeType of [...themeTypes, "email"]) {
144
+ if (!fs.existsSync(pathJoin(srcDirPath, themeType))) {
145
+ continue;
146
+ }
147
+ return { themeSrcDirPath: srcDirPath };
148
+ }
149
+ console.log(chalk.red([
150
+ "Can't locate your keycloak theme source directory.",
151
+ "See: https://docs.keycloakify.dev/v/v10/keycloakify-in-my-app/collocation"
152
+ ].join("\n")));
153
+ process.exit(1);
154
+ })();
155
+ const recordIsImplementedByThemeType = objectFromEntries(["login", "account", "email"].map(themeType => [
156
+ themeType,
157
+ fs.existsSync(pathJoin(themeSrcDirPath, themeType))
158
+ ]));
159
+ const themeNames = (() => {
160
+ if (buildOptions.themeName === undefined) {
161
+ return [
162
+ parsedPackageJson.name
163
+ .replace(/^@(.*)/, "$1")
164
+ .split("/")
165
+ .join("-")
166
+ ];
167
+ }
168
+ if (typeof buildOptions.themeName === "string") {
169
+ return [buildOptions.themeName];
170
+ }
171
+ const [mainThemeName, ...themeVariantNames] = buildOptions.themeName;
172
+ assert(mainThemeName !== undefined);
173
+ return [mainThemeName, ...themeVariantNames];
174
+ })();
175
+ const projectBuildDirPath = (() => {
176
+ webpack: {
177
+ if (resolvedViteConfig !== undefined) {
178
+ break webpack;
179
+ }
180
+ if (buildOptions.projectBuildDirPath !== undefined) {
181
+ return getAbsoluteAndInOsFormatPath({
182
+ pathIsh: buildOptions.projectBuildDirPath,
183
+ cwd: projectDirPath
184
+ });
185
+ }
186
+ return pathJoin(projectDirPath, "build");
187
+ }
188
+ return pathJoin(projectDirPath, resolvedViteConfig.buildDir);
189
+ })();
190
+ const { npmWorkspaceRootDirPath } = getNpmWorkspaceRootDirPath({
191
+ projectDirPath,
192
+ dependencyExpected: "keycloakify"
193
+ });
194
+ const bundler = resolvedViteConfig !== undefined ? "vite" : "webpack";
195
+ return {
196
+ bundler,
197
+ themeVersion: (_b = (_a = buildOptions.themeVersion) !== null && _a !== void 0 ? _a : parsedPackageJson.version) !== null && _b !== void 0 ? _b : "0.0.0",
198
+ themeNames,
199
+ extraThemeProperties: buildOptions.extraThemeProperties,
200
+ groupId: (() => {
201
+ var _a, _b, _c, _d, _e;
202
+ const fallbackGroupId = `${themeNames[0]}.keycloak`;
203
+ return ((_b = (_a = process.env.KEYCLOAKIFY_GROUP_ID) !== null && _a !== void 0 ? _a : buildOptions.groupId) !== null && _b !== void 0 ? _b : (parsedPackageJson.homepage === undefined
204
+ ? fallbackGroupId
205
+ : (_e = (_d = (_c = urlParse(parsedPackageJson.homepage)
206
+ .host) === null || _c === void 0 ? void 0 : _c.replace(/:[0-9]+$/, "")) === null || _d === void 0 ? void 0 : _d.split(".").reverse().join(".")) !== null && _e !== void 0 ? _e : fallbackGroupId) + ".keycloak");
207
+ })(),
208
+ artifactId: (_d = (_c = process.env.KEYCLOAKIFY_ARTIFACT_ID) !== null && _c !== void 0 ? _c : buildOptions.artifactId) !== null && _d !== void 0 ? _d : `${themeNames[0]}-keycloak-theme`,
209
+ loginThemeResourcesFromKeycloakVersion: (_e = buildOptions.loginThemeResourcesFromKeycloakVersion) !== null && _e !== void 0 ? _e : "24.0.4",
210
+ projectDirPath,
211
+ projectBuildDirPath,
212
+ keycloakifyBuildDirPath: (() => {
213
+ if (buildOptions.keycloakifyBuildDirPath !== undefined) {
214
+ return getAbsoluteAndInOsFormatPath({
215
+ pathIsh: buildOptions.keycloakifyBuildDirPath,
216
+ cwd: projectDirPath
217
+ });
218
+ }
219
+ return pathJoin(projectDirPath, (resolvedViteConfig === null || resolvedViteConfig === void 0 ? void 0 : resolvedViteConfig.buildDir) === undefined
220
+ ? "build_keycloak"
221
+ : `${resolvedViteConfig.buildDir}_keycloak`);
222
+ })(),
223
+ publicDirPath: (() => {
224
+ if (process.env.PUBLIC_DIR_PATH !== undefined) {
225
+ return getAbsoluteAndInOsFormatPath({
226
+ pathIsh: process.env.PUBLIC_DIR_PATH,
227
+ cwd: projectDirPath
228
+ });
229
+ }
230
+ webpack: {
231
+ if (resolvedViteConfig !== undefined) {
232
+ break webpack;
233
+ }
234
+ if (buildOptions.publicDirPath !== undefined) {
235
+ return getAbsoluteAndInOsFormatPath({
236
+ pathIsh: buildOptions.publicDirPath,
237
+ cwd: projectDirPath
238
+ });
239
+ }
240
+ return pathJoin(projectDirPath, "public");
241
+ }
242
+ return pathJoin(projectDirPath, resolvedViteConfig.publicDir);
243
+ })(),
244
+ cacheDirPath: (() => {
245
+ const cacheDirPath = pathJoin((() => {
246
+ if (process.env.XDG_CACHE_HOME !== undefined) {
247
+ return getAbsoluteAndInOsFormatPath({
248
+ pathIsh: process.env.XDG_CACHE_HOME,
249
+ cwd: process.cwd()
250
+ });
251
+ }
252
+ return pathJoin(npmWorkspaceRootDirPath, "node_modules", ".cache");
253
+ })(), "keycloakify");
254
+ return cacheDirPath;
255
+ })(),
256
+ urlPathname: (() => {
257
+ webpack: {
258
+ if (resolvedViteConfig !== undefined) {
259
+ break webpack;
260
+ }
261
+ const { homepage } = parsedPackageJson;
262
+ let url = undefined;
263
+ if (homepage !== undefined) {
264
+ url = new URL(homepage);
265
+ }
266
+ if (url === undefined) {
267
+ return undefined;
268
+ }
269
+ const out = url.pathname.replace(/([^/])$/, "$1/");
270
+ return out === "/" ? undefined : out;
271
+ }
272
+ return resolvedViteConfig.urlPathname;
273
+ })(),
274
+ assetsDirPath: (() => {
275
+ webpack: {
276
+ if (resolvedViteConfig !== undefined) {
277
+ break webpack;
278
+ }
279
+ if (buildOptions.staticDirPathInProjectBuildDirPath !== undefined) {
280
+ getAbsoluteAndInOsFormatPath({
281
+ pathIsh: buildOptions.staticDirPathInProjectBuildDirPath,
282
+ cwd: projectBuildDirPath
283
+ });
284
+ }
285
+ return pathJoin(projectBuildDirPath, "static");
286
+ }
287
+ return pathJoin(projectBuildDirPath, resolvedViteConfig.assetsDir);
288
+ })(),
289
+ npmWorkspaceRootDirPath,
290
+ kcContextExclusionsFtlCode: (() => {
291
+ if (buildOptions.kcContextExclusionsFtl === undefined) {
292
+ return undefined;
293
+ }
294
+ if (buildOptions.kcContextExclusionsFtl.endsWith(".ftl")) {
295
+ const kcContextExclusionsFtlPath = getAbsoluteAndInOsFormatPath({
296
+ pathIsh: buildOptions.kcContextExclusionsFtl,
297
+ cwd: projectDirPath
298
+ });
299
+ return fs.readFileSync(kcContextExclusionsFtlPath).toString("utf8");
300
+ }
301
+ return buildOptions.kcContextExclusionsFtl;
302
+ })(),
303
+ environmentVariables: (_f = buildOptions.environmentVariables) !== null && _f !== void 0 ? _f : [],
304
+ recordIsImplementedByThemeType,
305
+ themeSrcDirPath,
306
+ jarTargets: (() => {
307
+ const getDefaultJarFileBasename = (range) => `keycloak-theme-for-kc-${range}.jar`;
308
+ build_for_specific_keycloak_major_version: {
309
+ const buildForKeycloakMajorVersionNumber = (() => {
310
+ const envValue = process.env[buildForKeycloakMajorVersionEnvName];
311
+ if (envValue === undefined) {
312
+ return undefined;
313
+ }
314
+ const major = parseInt(envValue);
315
+ assert(!isNaN(major));
316
+ return major;
317
+ })();
318
+ if (buildForKeycloakMajorVersionNumber === undefined) {
319
+ break build_for_specific_keycloak_major_version;
320
+ }
321
+ const keycloakVersionRange = (() => {
322
+ const doesImplementAccountTheme = recordIsImplementedByThemeType.account;
323
+ if (doesImplementAccountTheme) {
324
+ const keycloakVersionRange = (() => {
325
+ if (buildForKeycloakMajorVersionNumber <= 21) {
326
+ return "21-and-below";
327
+ }
328
+ assert(buildForKeycloakMajorVersionNumber !== 22);
329
+ if (buildForKeycloakMajorVersionNumber === 23) {
330
+ return "23";
331
+ }
332
+ if (buildForKeycloakMajorVersionNumber === 24) {
333
+ return "24";
334
+ }
335
+ return "25-and-above";
336
+ })();
337
+ assert();
338
+ return keycloakVersionRange;
339
+ }
340
+ else {
341
+ const keycloakVersionRange = (() => {
342
+ if (buildForKeycloakMajorVersionNumber <= 21) {
343
+ return "21-and-below";
344
+ }
345
+ return "22-and-above";
346
+ })();
347
+ assert();
348
+ return keycloakVersionRange;
349
+ }
350
+ })();
351
+ const jarFileBasename = (() => {
352
+ use_custom_jar_basename: {
353
+ const { keycloakVersionTargets } = buildOptions;
354
+ if (keycloakVersionTargets === undefined) {
355
+ break use_custom_jar_basename;
356
+ }
357
+ const entry = objectEntries(keycloakVersionTargets).find(([keycloakVersionRange_entry]) => keycloakVersionRange_entry === keycloakVersionRange);
358
+ if (entry === undefined) {
359
+ break use_custom_jar_basename;
360
+ }
361
+ const maybeJarFileBasename = entry[1];
362
+ if (typeof maybeJarFileBasename !== "string") {
363
+ break use_custom_jar_basename;
364
+ }
365
+ return maybeJarFileBasename;
366
+ }
367
+ return getDefaultJarFileBasename(keycloakVersionRange);
368
+ })();
369
+ return [
370
+ {
371
+ keycloakVersionRange,
372
+ jarFileBasename
373
+ }
374
+ ];
375
+ }
376
+ const jarTargets_default = (() => {
377
+ const jarTargets = [];
378
+ if (recordIsImplementedByThemeType.account) {
379
+ for (const keycloakVersionRange of [
380
+ "21-and-below",
381
+ "23",
382
+ "24",
383
+ "25-and-above"
384
+ ]) {
385
+ assert(true);
386
+ jarTargets.push({
387
+ keycloakVersionRange,
388
+ jarFileBasename: getDefaultJarFileBasename(keycloakVersionRange)
389
+ });
390
+ }
391
+ }
392
+ else {
393
+ for (const keycloakVersionRange of [
394
+ "21-and-below",
395
+ "22-and-above"
396
+ ]) {
397
+ assert(true);
398
+ jarTargets.push({
399
+ keycloakVersionRange,
400
+ jarFileBasename: getDefaultJarFileBasename(keycloakVersionRange)
401
+ });
402
+ }
403
+ }
404
+ return jarTargets;
405
+ })();
406
+ if (buildOptions.keycloakVersionTargets === undefined) {
407
+ return jarTargets_default;
408
+ }
409
+ if (buildOptions.keycloakVersionTargets.hasAccountTheme !==
410
+ recordIsImplementedByThemeType.account) {
411
+ console.log(chalk.red((() => {
412
+ const { keycloakVersionTargets } = buildOptions;
413
+ let message = `Bad ${symToStr({ keycloakVersionTargets })} configuration.\n`;
414
+ if (keycloakVersionTargets.hasAccountTheme) {
415
+ message +=
416
+ "Your codebase does not seem to implement an account theme ";
417
+ }
418
+ else {
419
+ message += "Your codebase implements an account theme ";
420
+ }
421
+ const { hasAccountTheme } = keycloakVersionTargets;
422
+ message += `but you have set ${symToStr({ keycloakVersionTargets })}.${symToStr({ hasAccountTheme })}`;
423
+ message += ` to ${hasAccountTheme} in your `;
424
+ message += (() => {
425
+ switch (bundler) {
426
+ case "vite":
427
+ return "vite.config.ts";
428
+ case "webpack":
429
+ return "package.json";
430
+ }
431
+ assert(false);
432
+ })();
433
+ message += `. Please set it to ${!hasAccountTheme} `;
434
+ message +=
435
+ "and fill up the relevant keycloak version ranges.\n";
436
+ message += "Example:\n";
437
+ message += JSON.stringify(id({
438
+ keycloakVersionTargets: Object.assign({ hasAccountTheme: recordIsImplementedByThemeType.account }, objectFromEntries(jarTargets_default.map(({ keycloakVersionRange, jarFileBasename }) => [
439
+ keycloakVersionRange,
440
+ jarFileBasename
441
+ ])))
442
+ }), null, 2);
443
+ message +=
444
+ "\nSee: https://docs.keycloakify.dev/v/v10/targetting-specific-keycloak-versions";
445
+ return message;
446
+ })()));
447
+ process.exit(1);
448
+ }
449
+ const jarTargets = [];
450
+ const _a = buildOptions.keycloakVersionTargets, { hasAccountTheme } = _a, rest = __rest(_a, ["hasAccountTheme"]);
451
+ for (const [keycloakVersionRange, jarNameOrBoolean] of objectEntries(rest)) {
452
+ if (jarNameOrBoolean === false) {
453
+ continue;
454
+ }
455
+ if (jarNameOrBoolean === true) {
456
+ jarTargets.push({
457
+ keycloakVersionRange: keycloakVersionRange,
458
+ jarFileBasename: getDefaultJarFileBasename(keycloakVersionRange)
459
+ });
460
+ continue;
461
+ }
462
+ const jarFileBasename = jarNameOrBoolean;
463
+ if (!jarFileBasename.endsWith(".jar")) {
464
+ console.log(chalk.red(`Bad ${jarFileBasename} should end with '.jar'\n`));
465
+ process.exit(1);
466
+ }
467
+ if (jarFileBasename.includes("/") || jarFileBasename.includes("\\")) {
468
+ console.log(chalk.red([
469
+ `Invalid ${jarFileBasename}. It's not supposed to be a path,`,
470
+ `Only the basename of the jar file is expected.`,
471
+ `Example: keycloak-theme.jar`
472
+ ].join(" ")));
473
+ process.exit(1);
474
+ }
475
+ jarTargets.push({
476
+ keycloakVersionRange: keycloakVersionRange,
477
+ jarFileBasename: jarNameOrBoolean
478
+ });
479
+ }
480
+ if (jarTargets.length === 0) {
481
+ console.log(chalk.red("All jar targets are disabled. Please enable at least one jar target."));
482
+ process.exit(1);
483
+ }
484
+ return jarTargets;
485
+ })()
486
+ };
487
+ }
488
+ //# sourceMappingURL=buildContext.js.map
@@ -0,0 +1,59 @@
1
+ export const nameOfTheLocalizationRealmOverridesUserProfileProperty = "__localizationRealmOverridesUserProfile";
2
+ export const keycloak_resources = "keycloak-resources";
3
+ export const resources_common = "resources-common";
4
+ export const lastKeycloakVersionWithAccountV1 = "21.1.2";
5
+ export const basenameOfTheKeycloakifyResourcesDir = "dist";
6
+ export const themeTypes = ["login", "account"];
7
+ export const accountV1ThemeName = "account-v1";
8
+ export const vitePluginSubScriptEnvNames = {
9
+ runPostBuildScript: "KEYCLOAKIFY_RUN_POST_BUILD_SCRIPT",
10
+ resolveViteConfig: "KEYCLOAKIFY_RESOLVE_VITE_CONFIG"
11
+ };
12
+ export const buildForKeycloakMajorVersionEnvName = "KEYCLOAKIFY_BUILD_FOR_KEYCLOAK_MAJOR_VERSION";
13
+ export const loginThemePageIds = [
14
+ "login.ftl",
15
+ "login-username.ftl",
16
+ "login-password.ftl",
17
+ "webauthn-authenticate.ftl",
18
+ "webauthn-register.ftl",
19
+ "register.ftl",
20
+ "info.ftl",
21
+ "error.ftl",
22
+ "login-reset-password.ftl",
23
+ "login-verify-email.ftl",
24
+ "terms.ftl",
25
+ "login-oauth2-device-verify-user-code.ftl",
26
+ "login-oauth-grant.ftl",
27
+ "login-otp.ftl",
28
+ "login-update-profile.ftl",
29
+ "login-update-password.ftl",
30
+ "login-idp-link-confirm.ftl",
31
+ "login-idp-link-email.ftl",
32
+ "login-page-expired.ftl",
33
+ "login-config-totp.ftl",
34
+ "logout-confirm.ftl",
35
+ "idp-review-user-profile.ftl",
36
+ "update-email.ftl",
37
+ "select-authenticator.ftl",
38
+ "saml-post-form.ftl",
39
+ "delete-credential.ftl",
40
+ "code.ftl",
41
+ "delete-account-confirm.ftl",
42
+ "frontchannel-logout.ftl",
43
+ "login-recovery-authn-code-config.ftl",
44
+ "login-recovery-authn-code-input.ftl",
45
+ "login-reset-otp.ftl",
46
+ "login-x509-info.ftl",
47
+ "webauthn-error.ftl"
48
+ ];
49
+ export const accountThemePageIds = [
50
+ "password.ftl",
51
+ "account.ftl",
52
+ "sessions.ftl",
53
+ "totp.ftl",
54
+ "applications.ftl",
55
+ "log.ftl",
56
+ "federatedIdentity.ftl"
57
+ ];
58
+ export const containerName = "keycloak-keycloakify";
59
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,61 @@
1
+ import { downloadKeycloakStaticResources } from "./downloadKeycloakStaticResources";
2
+ import { join as pathJoin, relative as pathRelative } from "path";
3
+ import { themeTypes, keycloak_resources, lastKeycloakVersionWithAccountV1 } from "../shared/constants";
4
+ import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
5
+ import { assert } from "tsafe/assert";
6
+ import * as fs from "fs";
7
+ import { rmSync } from "../tools/fs.rmSync";
8
+ assert();
9
+ export async function copyKeycloakResourcesToPublic(params) {
10
+ const { buildContext } = params;
11
+ const destDirPath = pathJoin(buildContext.publicDirPath, keycloak_resources);
12
+ const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo");
13
+ const keycloakifyBuildinfoRaw = JSON.stringify({
14
+ destDirPath,
15
+ keycloakifyVersion: readThisNpmPackageVersion(),
16
+ buildContext: {
17
+ loginThemeResourcesFromKeycloakVersion: readThisNpmPackageVersion(),
18
+ cacheDirPath: pathRelative(destDirPath, buildContext.cacheDirPath),
19
+ npmWorkspaceRootDirPath: pathRelative(destDirPath, buildContext.npmWorkspaceRootDirPath)
20
+ }
21
+ }, null, 2);
22
+ skip_if_already_done: {
23
+ if (!fs.existsSync(keycloakifyBuildinfoFilePath)) {
24
+ break skip_if_already_done;
25
+ }
26
+ const keycloakifyBuildinfoRaw_previousRun = fs
27
+ .readFileSync(keycloakifyBuildinfoFilePath)
28
+ .toString("utf8");
29
+ if (keycloakifyBuildinfoRaw_previousRun !== keycloakifyBuildinfoRaw) {
30
+ break skip_if_already_done;
31
+ }
32
+ return;
33
+ }
34
+ rmSync(destDirPath, { force: true, recursive: true });
35
+ fs.mkdirSync(destDirPath, { recursive: true });
36
+ fs.writeFileSync(pathJoin(destDirPath, ".gitignore"), Buffer.from("*", "utf8"));
37
+ for (const themeType of themeTypes) {
38
+ await downloadKeycloakStaticResources({
39
+ keycloakVersion: (() => {
40
+ switch (themeType) {
41
+ case "login":
42
+ return buildContext.loginThemeResourcesFromKeycloakVersion;
43
+ case "account":
44
+ return lastKeycloakVersionWithAccountV1;
45
+ }
46
+ })(),
47
+ themeType,
48
+ themeDirPath: destDirPath,
49
+ buildContext
50
+ });
51
+ }
52
+ fs.writeFileSync(pathJoin(destDirPath, "README.txt"), Buffer.from(
53
+ // prettier-ignore
54
+ [
55
+ "This is just a test folder that helps develop",
56
+ "the login and register page without having to run a Keycloak container\n",
57
+ "This directory will be automatically excluded from the final build."
58
+ ].join(" ")));
59
+ fs.writeFileSync(keycloakifyBuildinfoFilePath, Buffer.from(keycloakifyBuildinfoRaw, "utf8"));
60
+ }
61
+ //# sourceMappingURL=copyKeycloakResourcesToPublic.js.map
@@ -0,0 +1,123 @@
1
+ import { join as pathJoin, relative as pathRelative } from "path";
2
+ import { assert } from "tsafe/assert";
3
+ import { lastKeycloakVersionWithAccountV1 } from "./constants";
4
+ import { downloadAndExtractArchive } from "../tools/downloadAndExtractArchive";
5
+ assert();
6
+ export async function downloadKeycloakDefaultTheme(params) {
7
+ const { keycloakVersion, buildContext } = params;
8
+ let kcNodeModulesKeepFilePaths = undefined;
9
+ let kcNodeModulesKeepFilePaths_lastAccountV1 = undefined;
10
+ const { extractedDirPath } = await downloadAndExtractArchive({
11
+ url: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`,
12
+ cacheDirPath: buildContext.cacheDirPath,
13
+ npmWorkspaceRootDirPath: buildContext.npmWorkspaceRootDirPath,
14
+ uniqueIdOfOnOnArchiveFile: "downloadKeycloakDefaultTheme",
15
+ onArchiveFile: async (params) => {
16
+ const fileRelativePath = pathRelative("theme", params.fileRelativePath);
17
+ if (fileRelativePath.startsWith("..")) {
18
+ return;
19
+ }
20
+ const { readFile, writeFile } = params;
21
+ skip_keycloak_v2: {
22
+ if (!fileRelativePath.startsWith(pathJoin("keycloak.v2"))) {
23
+ break skip_keycloak_v2;
24
+ }
25
+ return;
26
+ }
27
+ last_account_v1_transformations: {
28
+ if (lastKeycloakVersionWithAccountV1 !== keycloakVersion) {
29
+ break last_account_v1_transformations;
30
+ }
31
+ skip_web_modules: {
32
+ if (!fileRelativePath.startsWith(pathJoin("keycloak", "common", "resources", "web_modules"))) {
33
+ break skip_web_modules;
34
+ }
35
+ return;
36
+ }
37
+ skip_lib: {
38
+ if (!fileRelativePath.startsWith(pathJoin("keycloak", "common", "resources", "lib"))) {
39
+ break skip_lib;
40
+ }
41
+ return;
42
+ }
43
+ skip_node_modules: {
44
+ if (!fileRelativePath.startsWith(pathJoin("keycloak", "common", "resources", "node_modules"))) {
45
+ break skip_node_modules;
46
+ }
47
+ if (kcNodeModulesKeepFilePaths_lastAccountV1 === undefined) {
48
+ kcNodeModulesKeepFilePaths_lastAccountV1 = [
49
+ pathJoin("patternfly", "dist", "css", "patternfly.min.css"),
50
+ pathJoin("patternfly", "dist", "css", "patternfly-additions.min.css"),
51
+ pathJoin("patternfly", "dist", "fonts", "OpenSans-Regular-webfont.woff2"),
52
+ pathJoin("patternfly", "dist", "fonts", "OpenSans-Bold-webfont.woff2"),
53
+ pathJoin("patternfly", "dist", "fonts", "OpenSans-Light-webfont.woff2"),
54
+ pathJoin("patternfly", "dist", "fonts", "OpenSans-Semibold-webfont.woff2")
55
+ ];
56
+ }
57
+ for (const keepPath of kcNodeModulesKeepFilePaths_lastAccountV1) {
58
+ if (fileRelativePath.endsWith(keepPath)) {
59
+ break skip_node_modules;
60
+ }
61
+ }
62
+ return;
63
+ }
64
+ patch_account_css: {
65
+ if (fileRelativePath !==
66
+ pathJoin("keycloak", "account", "resources", "css", "account.css")) {
67
+ break patch_account_css;
68
+ }
69
+ await writeFile({
70
+ fileRelativePath,
71
+ modifiedData: Buffer.from((await readFile())
72
+ .toString("utf8")
73
+ .replace("top: -34px;", "top: -34px !important;"), "utf8")
74
+ });
75
+ return;
76
+ }
77
+ }
78
+ skip_unused_resources: {
79
+ if (keycloakVersion !== "24.0.4") {
80
+ break skip_unused_resources;
81
+ }
82
+ skip_node_modules: {
83
+ if (!fileRelativePath.startsWith(pathJoin("keycloak", "common", "resources", "node_modules"))) {
84
+ break skip_node_modules;
85
+ }
86
+ if (kcNodeModulesKeepFilePaths === undefined) {
87
+ kcNodeModulesKeepFilePaths = [
88
+ pathJoin("@patternfly", "patternfly", "patternfly.min.css"),
89
+ pathJoin("patternfly", "dist", "css", "patternfly.min.css"),
90
+ pathJoin("patternfly", "dist", "css", "patternfly-additions.min.css"),
91
+ pathJoin("patternfly", "dist", "fonts", "OpenSans-Regular-webfont.woff2"),
92
+ pathJoin("patternfly", "dist", "fonts", "OpenSans-Light-webfont.woff2"),
93
+ pathJoin("patternfly", "dist", "fonts", "fontawesome-webfont.woff2"),
94
+ pathJoin("jquery", "dist", "jquery.min.js")
95
+ ];
96
+ }
97
+ for (const keepPath of kcNodeModulesKeepFilePaths) {
98
+ if (fileRelativePath.endsWith(keepPath)) {
99
+ break skip_node_modules;
100
+ }
101
+ }
102
+ return;
103
+ }
104
+ skip_vendor: {
105
+ if (!fileRelativePath.startsWith(pathJoin("keycloak", "common", "resources", "vendor"))) {
106
+ break skip_vendor;
107
+ }
108
+ return;
109
+ }
110
+ skip_rollup_config: {
111
+ if (fileRelativePath !==
112
+ pathJoin("keycloak", "common", "resources", "rollup.config.js")) {
113
+ break skip_rollup_config;
114
+ }
115
+ return;
116
+ }
117
+ }
118
+ await writeFile({ fileRelativePath });
119
+ }
120
+ });
121
+ return { defaultThemeDirPath: extractedDirPath };
122
+ }
123
+ //# sourceMappingURL=downloadKeycloakDefaultTheme.js.map
@@ -0,0 +1,34 @@
1
+ import { transformCodebase } from "../tools/transformCodebase";
2
+ import { join as pathJoin } from "path";
3
+ import { downloadKeycloakDefaultTheme } from "./downloadKeycloakDefaultTheme";
4
+ import { resources_common } from "./constants";
5
+ import { assert } from "tsafe/assert";
6
+ import { existsAsync } from "../tools/fs.existsAsync";
7
+ assert();
8
+ export async function downloadKeycloakStaticResources(params) {
9
+ const { themeType, themeDirPath, keycloakVersion, buildContext } = params;
10
+ const { defaultThemeDirPath } = await downloadKeycloakDefaultTheme({
11
+ keycloakVersion,
12
+ buildContext
13
+ });
14
+ const resourcesDirPath = pathJoin(themeDirPath, themeType, "resources");
15
+ repatriate_base_resources: {
16
+ const srcDirPath = pathJoin(defaultThemeDirPath, "base", themeType, "resources");
17
+ if (!(await existsAsync(srcDirPath))) {
18
+ break repatriate_base_resources;
19
+ }
20
+ transformCodebase({
21
+ srcDirPath,
22
+ destDirPath: resourcesDirPath
23
+ });
24
+ }
25
+ transformCodebase({
26
+ srcDirPath: pathJoin(defaultThemeDirPath, "keycloak", themeType, "resources"),
27
+ destDirPath: resourcesDirPath
28
+ });
29
+ transformCodebase({
30
+ srcDirPath: pathJoin(defaultThemeDirPath, "keycloak", "common", "resources"),
31
+ destDirPath: pathJoin(resourcesDirPath, resources_common)
32
+ });
33
+ }
34
+ //# sourceMappingURL=downloadKeycloakStaticResources.js.map
@@ -0,0 +1,41 @@
1
+ import { assert } from "tsafe/assert";
2
+ import * as fs from "fs/promises";
3
+ import { join as pathJoin } from "path";
4
+ import { existsAsync } from "../tools/fs.existsAsync";
5
+ assert();
6
+ export async function generateKcGenTs(params) {
7
+ const { buildContext } = params;
8
+ const filePath = pathJoin(buildContext.themeSrcDirPath, "kc.gen.ts");
9
+ const currentContent = (await existsAsync(filePath))
10
+ ? await fs.readFile(filePath)
11
+ : undefined;
12
+ const newContent = Buffer.from([
13
+ `/* prettier-ignore-start */`,
14
+ ``,
15
+ `/* eslint-disable */`,
16
+ ``,
17
+ `// @ts-nocheck`,
18
+ ``,
19
+ `// noinspection JSUnusedGlobalSymbols`,
20
+ ``,
21
+ `// This file is auto-generated by Keycloakify`,
22
+ ``,
23
+ `export type ThemeName = ${buildContext.themeNames.map(themeName => `"${themeName}"`).join(" | ")};`,
24
+ ``,
25
+ `export const themeNames: ThemeName[] = [${buildContext.themeNames.map(themeName => `"${themeName}"`).join(", ")}];`,
26
+ ``,
27
+ `export type KcEnvName = ${buildContext.environmentVariables.length === 0 ? "never" : buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(" | ")};`,
28
+ ``,
29
+ `export const kcEnvNames: KcEnvName[] = [${buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(", ")}];`,
30
+ ``,
31
+ `export const kcEnvDefaults: Record<KcEnvName, string> = ${JSON.stringify(Object.fromEntries(buildContext.environmentVariables.map(({ name, default: defaultValue }) => [name, defaultValue])), null, 2)};`,
32
+ ``,
33
+ `/* prettier-ignore-end */`,
34
+ ``
35
+ ].join("\n"), "utf8");
36
+ if (currentContent !== undefined && currentContent.equals(newContent)) {
37
+ return;
38
+ }
39
+ await fs.writeFile(filePath, newContent);
40
+ }
41
+ //# sourceMappingURL=generateKcGenTs.js.map
@@ -0,0 +1,20 @@
1
+ import { join as pathJoin, dirname as pathDirname } from "path";
2
+ import * as fs from "fs";
3
+ export function writeMetaInfKeycloakThemes(params) {
4
+ const { resourcesDirPath, getNewMetaInfKeycloakTheme } = params;
5
+ const filePath = pathJoin(resourcesDirPath, "META-INF", "keycloak-themes.json");
6
+ const currentMetaInfKeycloakTheme = !fs.existsSync(filePath)
7
+ ? undefined
8
+ : JSON.parse(fs.readFileSync(filePath).toString("utf8"));
9
+ const newMetaInfKeycloakThemes = getNewMetaInfKeycloakTheme({
10
+ metaInfKeycloakTheme: currentMetaInfKeycloakTheme
11
+ });
12
+ {
13
+ const dirPath = pathDirname(filePath);
14
+ if (!fs.existsSync(dirPath)) {
15
+ fs.mkdirSync(dirPath, { recursive: true });
16
+ }
17
+ }
18
+ fs.writeFileSync(filePath, Buffer.from(JSON.stringify(newMetaInfKeycloakThemes, null, 2), "utf8"));
19
+ }
20
+ //# sourceMappingURL=metaInfKeycloakThemes.js.map
@@ -0,0 +1,76 @@
1
+ import { getLatestsSemVersionedTagFactory } from "../tools/octokit-addons/getLatestsSemVersionedTag";
2
+ import { Octokit } from "@octokit/rest";
3
+ import cliSelect from "cli-select";
4
+ import { SemVer } from "../tools/SemVer";
5
+ import { join as pathJoin, dirname as pathDirname } from "path";
6
+ import * as fs from "fs";
7
+ import { id } from "tsafe/id";
8
+ export async function promptKeycloakVersion(params) {
9
+ const { startingFromMajor, excludeMajorVersions, cacheDirPath } = params;
10
+ const { getLatestsSemVersionedTag } = (() => {
11
+ const { octokit } = (() => {
12
+ const githubToken = process.env.GITHUB_TOKEN;
13
+ const octokit = new Octokit(githubToken === undefined ? undefined : { auth: githubToken });
14
+ return { octokit };
15
+ })();
16
+ const { getLatestsSemVersionedTag } = getLatestsSemVersionedTagFactory({
17
+ octokit
18
+ });
19
+ return { getLatestsSemVersionedTag };
20
+ })();
21
+ const semVersionedTagByMajor = new Map();
22
+ const semVersionedTags = await (async () => {
23
+ const cacheFilePath = pathJoin(cacheDirPath, "keycloak-versions.json");
24
+ use_cache: {
25
+ if (!fs.existsSync(cacheFilePath)) {
26
+ break use_cache;
27
+ }
28
+ const cache = JSON.parse(fs.readFileSync(cacheFilePath).toString("utf8"));
29
+ if (Date.now() - cache.time > 3600000) {
30
+ fs.unlinkSync(cacheFilePath);
31
+ break use_cache;
32
+ }
33
+ return cache.semVersionedTags;
34
+ }
35
+ const semVersionedTags = await getLatestsSemVersionedTag({
36
+ count: 50,
37
+ owner: "keycloak",
38
+ repo: "keycloak"
39
+ });
40
+ {
41
+ const dirPath = pathDirname(cacheFilePath);
42
+ if (!fs.existsSync(dirPath)) {
43
+ fs.mkdirSync(dirPath, { recursive: true });
44
+ }
45
+ }
46
+ fs.writeFileSync(cacheFilePath, JSON.stringify(id({
47
+ time: Date.now(),
48
+ semVersionedTags
49
+ }), null, 2));
50
+ return semVersionedTags;
51
+ })();
52
+ semVersionedTags.forEach(semVersionedTag => {
53
+ if (startingFromMajor !== undefined &&
54
+ semVersionedTag.version.major < startingFromMajor) {
55
+ return;
56
+ }
57
+ if (excludeMajorVersions.includes(semVersionedTag.version.major)) {
58
+ return;
59
+ }
60
+ const currentSemVersionedTag = semVersionedTagByMajor.get(semVersionedTag.version.major);
61
+ if (currentSemVersionedTag !== undefined &&
62
+ SemVer.compare(semVersionedTag.version, currentSemVersionedTag.version) === -1) {
63
+ return;
64
+ }
65
+ semVersionedTagByMajor.set(semVersionedTag.version.major, semVersionedTag);
66
+ });
67
+ const lastMajorVersions = Array.from(semVersionedTagByMajor.values()).map(({ tag }) => tag);
68
+ const { value } = await cliSelect({
69
+ values: lastMajorVersions
70
+ }).catch(() => {
71
+ process.exit(-1);
72
+ });
73
+ const keycloakVersion = value.split(" ")[0];
74
+ return { keycloakVersion };
75
+ }
76
+ //# sourceMappingURL=promptKeycloakVersion.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "10.0.0-rc.70",
3
+ "version": "10.0.0-rc.71",
4
4
  "description": "Create Keycloak themes using React",
5
5
  "repository": {
6
6
  "type": "git",
@@ -786,6 +786,15 @@
786
786
  "bin/837.index.js",
787
787
  "bin/932.index.js",
788
788
  "bin/97.index.js",
789
+ "bin/shared/buildContext.js",
790
+ "bin/shared/constants.js",
791
+ "bin/shared/copyKeycloakResourcesToPublic.js",
792
+ "bin/shared/downloadKeycloakDefaultTheme.js",
793
+ "bin/shared/downloadKeycloakStaticResources.js",
794
+ "bin/shared/generateKcGenTs.js",
795
+ "bin/shared/KeycloakVersionRange.js",
796
+ "bin/shared/metaInfKeycloakThemes.js",
797
+ "bin/shared/promptKeycloakVersion.js",
789
798
  "bin/shared/buildContext.d.ts",
790
799
  "bin/shared/constants.d.ts",
791
800
  "bin/shared/copyKeycloakResourcesToPublic.d.ts",