keycloakify 11.5.3 → 11.6.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 (36) hide show
  1. package/bin/{682.index.js → 153.index.js} +300 -52
  2. package/bin/356.index.js +48 -25
  3. package/bin/{573.index.js → 880.index.js} +155 -9
  4. package/bin/main.js +6 -5
  5. package/bin/start-keycloak/realmConfig/{ParsedRealmJson.d.ts → ParsedRealmJson/ParsedRealmJson.d.ts} +2 -3
  6. package/bin/start-keycloak/realmConfig/ParsedRealmJson/index.d.ts +3 -0
  7. package/bin/start-keycloak/realmConfig/ParsedRealmJson/readRealmJsonFile.d.ts +4 -0
  8. package/bin/start-keycloak/realmConfig/ParsedRealmJson/writeRealmJsonFile.d.ts +6 -0
  9. package/bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.d.ts +1 -4
  10. package/bin/tools/Stringifyable.d.ts +13 -0
  11. package/bin/tools/canonicalStringify.d.ts +5 -0
  12. package/bin/tools/createObjectThatThrowsIfAccessed.d.ts +21 -0
  13. package/package.json +18 -5
  14. package/src/bin/keycloakify/generateResources/generateResources.ts +162 -6
  15. package/src/bin/main.ts +4 -3
  16. package/src/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts +63 -24
  17. package/src/bin/start-keycloak/realmConfig/{ParsedRealmJson.ts → ParsedRealmJson/ParsedRealmJson.ts} +1 -19
  18. package/src/bin/start-keycloak/realmConfig/ParsedRealmJson/index.ts +3 -0
  19. package/src/bin/start-keycloak/realmConfig/ParsedRealmJson/readRealmJsonFile.ts +20 -0
  20. package/src/bin/start-keycloak/realmConfig/ParsedRealmJson/writeRealmJsonFile.ts +29 -0
  21. package/src/bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.ts +3 -4
  22. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-18.json +51 -33
  23. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-19.json +48 -30
  24. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-20.json +50 -32
  25. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-21.json +29 -11
  26. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-22.json +2201 -0
  27. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-23.json +25 -7
  28. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-24.json +26 -8
  29. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-25.json +26 -8
  30. package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-26.json +11 -11
  31. package/src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts +1 -1
  32. package/src/bin/start-keycloak/realmConfig/realmConfig.ts +15 -19
  33. package/src/bin/start-keycloak/start-keycloak.ts +131 -36
  34. package/src/bin/tools/Stringifyable.ts +99 -0
  35. package/src/bin/tools/canonicalStringify.ts +164 -0
  36. package/src/bin/tools/createObjectThatThrowsIfAccessed.ts +90 -0
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- exports.id = 573;
3
- exports.ids = [573];
2
+ exports.id = 880;
3
+ exports.ids = [880];
4
4
  exports.modules = {
5
5
 
6
6
  /***/ 73817:
@@ -314,7 +314,7 @@ function recastParseTs(filePath) {
314
314
 
315
315
  /***/ }),
316
316
 
317
- /***/ 82573:
317
+ /***/ 59880:
318
318
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
319
319
 
320
320
  // ESM COMPAT FLAG
@@ -788,6 +788,66 @@ var external_child_process_default = /*#__PURE__*/__webpack_require__.n(external
788
788
  // EXTERNAL MODULE: ./node_modules/properties-parser/index.js
789
789
  var properties_parser = __webpack_require__(44414);
790
790
  var properties_parser_default = /*#__PURE__*/__webpack_require__.n(properties_parser);
791
+ ;// CONCATENATED MODULE: ./dist/bin/tools/createObjectThatThrowsIfAccessed.js
792
+ const keyIsTrapped = "isTrapped_zSskDe9d";
793
+ class AccessError extends Error {
794
+ constructor(message) {
795
+ super(message);
796
+ Object.setPrototypeOf(this, new.target.prototype);
797
+ }
798
+ }
799
+ function createObjectThatThrowsIfAccessed(params) {
800
+ const { debugMessage = "", isPropertyWhitelisted = () => false } = params !== null && params !== void 0 ? params : {};
801
+ const get = (...args) => {
802
+ const [, prop] = args;
803
+ if (isPropertyWhitelisted(prop)) {
804
+ return Reflect.get(...args);
805
+ }
806
+ if (prop === keyIsTrapped) {
807
+ return true;
808
+ }
809
+ throw new AccessError(`Cannot access ${String(prop)} yet ${debugMessage}`);
810
+ };
811
+ const trappedObject = new Proxy({}, {
812
+ get,
813
+ set: get
814
+ });
815
+ return trappedObject;
816
+ }
817
+ function createObjectThatThrowsIfAccessedFactory(params) {
818
+ const { isPropertyWhitelisted } = params;
819
+ return {
820
+ createObjectThatThrowsIfAccessed: (params) => {
821
+ const { debugMessage } = params !== null && params !== void 0 ? params : {};
822
+ return createObjectThatThrowsIfAccessed({
823
+ debugMessage,
824
+ isPropertyWhitelisted
825
+ });
826
+ }
827
+ };
828
+ }
829
+ function isObjectThatThrowIfAccessed(obj) {
830
+ return obj[keyIsTrapped] === true;
831
+ }
832
+ const THROW_IF_ACCESSED = {
833
+ __brand: "THROW_IF_ACCESSED"
834
+ };
835
+ function createObjectWithSomePropertiesThatThrowIfAccessed(obj, debugMessage) {
836
+ return Object.defineProperties(obj, Object.fromEntries(Object.entries(obj)
837
+ .filter(([, value]) => value === THROW_IF_ACCESSED)
838
+ .map(([key]) => {
839
+ const getAndSet = () => {
840
+ throw new AccessError(`Cannot access ${key} yet ${debugMessage !== null && debugMessage !== void 0 ? debugMessage : ""}`);
841
+ };
842
+ const pd = {
843
+ get: getAndSet,
844
+ set: getAndSet,
845
+ enumerable: true
846
+ };
847
+ return [key, pd];
848
+ })));
849
+ }
850
+ //# sourceMappingURL=createObjectThatThrowsIfAccessed.js.map
791
851
  ;// CONCATENATED MODULE: ./dist/bin/keycloakify/generateResources/generateResources.js
792
852
 
793
853
 
@@ -808,6 +868,7 @@ var properties_parser_default = /*#__PURE__*/__webpack_require__.n(properties_pa
808
868
 
809
869
 
810
870
 
871
+
811
872
  (0,assert/* assert */.h)();
812
873
  async function generateResources(params) {
813
874
  var _a;
@@ -950,12 +1011,14 @@ async function generateResources(params) {
950
1011
  writeMessagePropertiesFilesByThemeType[themeType] =
951
1012
  writeMessagePropertiesFiles;
952
1013
  }
953
- bring_in_spas_messages: {
1014
+ bring_in_account_spa_messages: {
954
1015
  if (!isSpa) {
955
- break bring_in_spas_messages;
1016
+ break bring_in_account_spa_messages;
1017
+ }
1018
+ if (themeType !== "account") {
1019
+ break bring_in_account_spa_messages;
956
1020
  }
957
- (0,assert/* assert */.h)(themeType !== "login");
958
- const accountUiDirPath = external_child_process_.execSync(`npm list @keycloakify/keycloak-${themeType}-ui --parseable`, {
1021
+ const accountUiDirPath = external_child_process_.execSync(`npm list @keycloakify/keycloak-account-ui --parseable`, {
959
1022
  cwd: (0,external_path_.dirname)(buildContext.packageJsonFilePath)
960
1023
  })
961
1024
  .toString("utf8")
@@ -964,13 +1027,13 @@ async function generateResources(params) {
964
1027
  if (!external_fs_default().existsSync(messageDirPath_defaults)) {
965
1028
  throw new Error(`Please update @keycloakify/keycloak-account-ui to 25.0.4-rc.5 or later.`);
966
1029
  }
967
- const messagesDirPath_dest = (0,external_path_.join)(getThemeTypeDirPath({ themeName, themeType }), "messages");
1030
+ const messagesDirPath_dest = (0,external_path_.join)(getThemeTypeDirPath({ themeName, themeType: "account" }), "messages");
968
1031
  (0,transformCodebase/* transformCodebase */.N)({
969
1032
  srcDirPath: messageDirPath_defaults,
970
1033
  destDirPath: messagesDirPath_dest
971
1034
  });
972
1035
  apply_theme_changes: {
973
- const messagesDirPath_theme = (0,external_path_.join)(buildContext.themeSrcDirPath, themeType, "messages");
1036
+ const messagesDirPath_theme = (0,external_path_.join)(buildContext.themeSrcDirPath, "account", "messages");
974
1037
  if (!external_fs_default().existsSync(messagesDirPath_theme)) {
975
1038
  break apply_theme_changes;
976
1039
  }
@@ -993,6 +1056,89 @@ async function generateResources(params) {
993
1056
  languageTags = external_fs_default().readdirSync(messagesDirPath_dest)
994
1057
  .map(basename => basename.replace(/^messages_/, "").replace(/\.properties$/, ""));
995
1058
  }
1059
+ bring_in_admin_messages: {
1060
+ if (themeType !== "admin") {
1061
+ break bring_in_admin_messages;
1062
+ }
1063
+ const messagesDirPath_theme = (0,external_path_.join)(buildContext.themeSrcDirPath, "admin", "i18n");
1064
+ (0,assert/* assert */.h)(external_fs_default().existsSync(messagesDirPath_theme), `${messagesDirPath_theme} is supposed to exist`);
1065
+ const propertiesByLang = {};
1066
+ external_fs_default().readdirSync(messagesDirPath_theme).forEach(basename => {
1067
+ var _a;
1068
+ var _b;
1069
+ const parsedBasename = (() => {
1070
+ const match = basename.match(/^messages_([^.]+)\.properties$/);
1071
+ if (match === null) {
1072
+ return undefined;
1073
+ }
1074
+ const discriminator = match[1];
1075
+ const split = discriminator.split("_override");
1076
+ if (split.length === 1) {
1077
+ return {
1078
+ lang: discriminator,
1079
+ isOverride: false
1080
+ };
1081
+ }
1082
+ (0,assert/* assert */.h)(split.length === 2);
1083
+ if (split[1] === "") {
1084
+ return {
1085
+ lang: split[0],
1086
+ isOverride: true,
1087
+ themeName: undefined
1088
+ };
1089
+ }
1090
+ const match2 = split[1].match(/^_(.+)$/);
1091
+ (0,assert/* assert */.h)(match2 !== null);
1092
+ return {
1093
+ lang: split[0],
1094
+ isOverride: true,
1095
+ themeName: match2[1]
1096
+ };
1097
+ })();
1098
+ if (parsedBasename === undefined) {
1099
+ return;
1100
+ }
1101
+ (_a = propertiesByLang[_b = parsedBasename.lang]) !== null && _a !== void 0 ? _a : (propertiesByLang[_b] = {
1102
+ base: createObjectThatThrowsIfAccessed({
1103
+ debugMessage: `No base ${parsedBasename.lang} translation for admin theme`
1104
+ }),
1105
+ override: undefined,
1106
+ overrideByThemeName: {}
1107
+ });
1108
+ const buffer = external_fs_default().readFileSync((0,external_path_.join)(messagesDirPath_theme, basename));
1109
+ if (parsedBasename.isOverride === false) {
1110
+ propertiesByLang[parsedBasename.lang].base = buffer;
1111
+ return;
1112
+ }
1113
+ if (parsedBasename.themeName === undefined) {
1114
+ propertiesByLang[parsedBasename.lang].override = buffer;
1115
+ return;
1116
+ }
1117
+ propertiesByLang[parsedBasename.lang].overrideByThemeName[parsedBasename.themeName] = buffer;
1118
+ });
1119
+ writeMessagePropertiesFilesByThemeType.admin = ({ messageDirPath, themeName }) => {
1120
+ if (!external_fs_default().existsSync(messageDirPath)) {
1121
+ external_fs_default().mkdirSync(messageDirPath, { recursive: true });
1122
+ }
1123
+ Object.entries(propertiesByLang).forEach(([lang, { base, override, overrideByThemeName }]) => {
1124
+ (languageTags !== null && languageTags !== void 0 ? languageTags : (languageTags = [])).push(lang);
1125
+ const messages = properties_parser_default().parse(base.toString("utf8"));
1126
+ if (override !== undefined) {
1127
+ const overrideMessages = properties_parser_default().parse(override.toString("utf8"));
1128
+ Object.entries(overrideMessages).forEach(([key, value]) => (messages[key] = value));
1129
+ }
1130
+ if (themeName in overrideByThemeName) {
1131
+ const overrideMessages = properties_parser_default().parse(overrideByThemeName[themeName].toString("utf8"));
1132
+ Object.entries(overrideMessages).forEach(([key, value]) => (messages[key] = value));
1133
+ }
1134
+ const editor = properties_parser_default().createEditor();
1135
+ Object.entries(messages).forEach(([key, value]) => {
1136
+ editor.set(key, value);
1137
+ });
1138
+ external_fs_default().writeFileSync((0,external_path_.join)(messageDirPath, `messages_${lang}.properties`), Buffer.from(editor.toString(), "utf8"));
1139
+ });
1140
+ };
1141
+ }
996
1142
  keycloak_static_resources: {
997
1143
  if (isSpa) {
998
1144
  break keycloak_static_resources;
package/bin/main.js CHANGED
@@ -16153,7 +16153,7 @@ program
16153
16153
  .task({
16154
16154
  skip,
16155
16155
  handler: async ({ projectDirPath }) => {
16156
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(783), __nccwpck_require__.e(573)]).then(__nccwpck_require__.bind(__nccwpck_require__, 82573));
16156
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(783), __nccwpck_require__.e(880)]).then(__nccwpck_require__.bind(__nccwpck_require__, 59880));
16157
16157
  await command({ buildContext: getBuildContext({ projectDirPath }) });
16158
16158
  }
16159
16159
  });
@@ -16201,7 +16201,7 @@ program
16201
16201
  .task({
16202
16202
  skip,
16203
16203
  handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
16204
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(805), __nccwpck_require__.e(525), __nccwpck_require__.e(33), __nccwpck_require__.e(503), __nccwpck_require__.e(682)]).then(__nccwpck_require__.bind(__nccwpck_require__, 6682));
16204
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(805), __nccwpck_require__.e(525), __nccwpck_require__.e(33), __nccwpck_require__.e(503), __nccwpck_require__.e(153)]).then(__nccwpck_require__.bind(__nccwpck_require__, 43153));
16205
16205
  await command({
16206
16206
  buildContext: getBuildContext({ projectDirPath }),
16207
16207
  cliCommandOptions: {
@@ -16307,9 +16307,10 @@ program
16307
16307
  .option({
16308
16308
  key: "file",
16309
16309
  name: (() => {
16310
- const name = "file";
16311
- optionsKeys.push(name);
16312
- return name;
16310
+ const long = "file";
16311
+ const short = "f";
16312
+ optionsKeys.push(long, short);
16313
+ return { long, short };
16313
16314
  })(),
16314
16315
  description: [
16315
16316
  "Relative path of the file relative to the directory of your keycloak theme source",
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  export type ParsedRealmJson = {
2
3
  realm: string;
3
4
  loginTheme?: string;
@@ -40,6 +41,4 @@ export type ParsedRealmJson = {
40
41
  }[];
41
42
  }[];
42
43
  };
43
- export declare function readRealmJsonFile(params: {
44
- realmJsonFilePath: string;
45
- }): ParsedRealmJson;
44
+ export declare const zParsedRealmJson: z.ZodType<ParsedRealmJson, z.ZodTypeDef, ParsedRealmJson>;
@@ -0,0 +1,3 @@
1
+ export type { ParsedRealmJson } from "./ParsedRealmJson";
2
+ export { readRealmJsonFile } from "./readRealmJsonFile";
3
+ export { writeRealmJsonFile } from "./writeRealmJsonFile";
@@ -0,0 +1,4 @@
1
+ import { type ParsedRealmJson } from "./ParsedRealmJson";
2
+ export declare function readRealmJsonFile(params: {
3
+ realmJsonFilePath: string;
4
+ }): ParsedRealmJson;
@@ -0,0 +1,6 @@
1
+ import type { ParsedRealmJson } from "./ParsedRealmJson";
2
+ export declare function writeRealmJsonFile(params: {
3
+ realmJsonFilePath: string;
4
+ parsedRealmJson: ParsedRealmJson;
5
+ keycloakMajorVersionNumber: number;
6
+ }): Promise<void>;
@@ -1,7 +1,4 @@
1
- import { type ParsedRealmJson } from "../ParsedRealmJson";
2
- export declare function getDefaultRealmJsonFilePath(params: {
3
- keycloakMajorVersionNumber: number;
4
- }): string;
1
+ import type { ParsedRealmJson } from "../ParsedRealmJson/ParsedRealmJson";
5
2
  export declare const getSupportedKeycloakMajorVersions: () => number[];
6
3
  export declare function getDefaultConfig(params: {
7
4
  keycloakMajorVersionNumber: number;
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+ export type Stringifyable = StringifyableAtomic | StringifyableObject | StringifyableArray;
3
+ export type StringifyableAtomic = string | number | boolean | null;
4
+ interface StringifyableObject {
5
+ [key: string]: Stringifyable;
6
+ }
7
+ interface StringifyableArray extends Array<Stringifyable> {
8
+ }
9
+ export declare const zStringifyableAtomic: z.ZodType<StringifyableAtomic, z.ZodTypeDef, StringifyableAtomic>;
10
+ export declare const zStringifyable: z.ZodType<Stringifyable>;
11
+ export declare function getIsAtomic(stringifyable: Stringifyable): stringifyable is StringifyableAtomic;
12
+ export declare const getValueAtPath: (stringifyableObjectOrArray: Record<string, Stringifyable> | Stringifyable[], path: (string | number)[]) => Stringifyable | undefined;
13
+ export {};
@@ -0,0 +1,5 @@
1
+ import { type Stringifyable } from "./Stringifyable";
2
+ export declare function canonicalStringify(params: {
3
+ data: Record<string, Stringifyable> | Stringifyable[];
4
+ referenceData: Record<string, Stringifyable> | Stringifyable[];
5
+ }): string;
@@ -0,0 +1,21 @@
1
+ export declare class AccessError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare function createObjectThatThrowsIfAccessed<T extends object>(params?: {
5
+ debugMessage?: string;
6
+ isPropertyWhitelisted?: (prop: string | number | symbol) => boolean;
7
+ }): T;
8
+ export declare function createObjectThatThrowsIfAccessedFactory(params: {
9
+ isPropertyWhitelisted?: (prop: string | number | symbol) => boolean;
10
+ }): {
11
+ createObjectThatThrowsIfAccessed: <T extends object>(params?: {
12
+ debugMessage?: string;
13
+ }) => T;
14
+ };
15
+ export declare function isObjectThatThrowIfAccessed(obj: object): boolean;
16
+ export declare const THROW_IF_ACCESSED: {
17
+ __brand: string;
18
+ };
19
+ export declare function createObjectWithSomePropertiesThatThrowIfAccessed<T extends Record<string, unknown>>(obj: {
20
+ [K in keyof T]: T[K] | typeof THROW_IF_ACCESSED;
21
+ }, debugMessage?: string): T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "11.5.3",
3
+ "version": "11.6.0",
4
4
  "description": "Framework to create custom Keycloak UIs",
5
5
  "repository": {
6
6
  "type": "git",
@@ -704,13 +704,17 @@
704
704
  "src/bin/start-keycloak/index.ts",
705
705
  "src/bin/start-keycloak/keycloakify-logging-1.0.3.jar",
706
706
  "src/bin/start-keycloak/keycloakifyBuild.ts",
707
- "src/bin/start-keycloak/realmConfig/ParsedRealmJson.ts",
707
+ "src/bin/start-keycloak/realmConfig/ParsedRealmJson/ParsedRealmJson.ts",
708
+ "src/bin/start-keycloak/realmConfig/ParsedRealmJson/index.ts",
709
+ "src/bin/start-keycloak/realmConfig/ParsedRealmJson/readRealmJsonFile.ts",
710
+ "src/bin/start-keycloak/realmConfig/ParsedRealmJson/writeRealmJsonFile.ts",
708
711
  "src/bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.ts",
709
712
  "src/bin/start-keycloak/realmConfig/defaultConfig/index.ts",
710
713
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-18.json",
711
714
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-19.json",
712
715
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-20.json",
713
716
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-21.json",
717
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-22.json",
714
718
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-23.json",
715
719
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-24.json",
716
720
  "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-25.json",
@@ -724,10 +728,13 @@
724
728
  "src/bin/tools/OptionalIfCanBeUndefined.ts",
725
729
  "src/bin/tools/SemVer.ts",
726
730
  "src/bin/tools/String.prototype.replaceAll.ts",
731
+ "src/bin/tools/Stringifyable.ts",
727
732
  "src/bin/tools/assertNoPnpmDlx.ts",
733
+ "src/bin/tools/canonicalStringify.ts",
728
734
  "src/bin/tools/crawl.ts",
729
735
  "src/bin/tools/crawlAsync.ts",
730
736
  "src/bin/tools/crc32.ts",
737
+ "src/bin/tools/createObjectThatThrowsIfAccessed.ts",
731
738
  "src/bin/tools/deflate.ts",
732
739
  "src/bin/tools/downloadAndExtractArchive.ts",
733
740
  "src/bin/tools/escapeStringForPropertiesFile.ts",
@@ -1080,15 +1087,20 @@
1080
1087
  "bin/start-keycloak/realmConfig/defaultConfig/index.d.ts",
1081
1088
  "bin/start-keycloak/realmConfig/dumpContainerConfig.d.ts",
1082
1089
  "bin/start-keycloak/realmConfig/index.d.ts",
1083
- "bin/start-keycloak/realmConfig/ParsedRealmJson.d.ts",
1090
+ "bin/start-keycloak/realmConfig/ParsedRealmJson/index.d.ts",
1091
+ "bin/start-keycloak/realmConfig/ParsedRealmJson/ParsedRealmJson.d.ts",
1092
+ "bin/start-keycloak/realmConfig/ParsedRealmJson/readRealmJsonFile.d.ts",
1093
+ "bin/start-keycloak/realmConfig/ParsedRealmJson/writeRealmJsonFile.d.ts",
1084
1094
  "bin/start-keycloak/realmConfig/prepareRealmConfig.d.ts",
1085
1095
  "bin/start-keycloak/realmConfig/realmConfig.d.ts",
1086
1096
  "bin/start-keycloak/start-keycloak.d.ts",
1087
1097
  "bin/start-keycloak/startViteDevServer.d.ts",
1088
1098
  "bin/tools/assertNoPnpmDlx.d.ts",
1099
+ "bin/tools/canonicalStringify.d.ts",
1089
1100
  "bin/tools/crawl.d.ts",
1090
1101
  "bin/tools/crawlAsync.d.ts",
1091
1102
  "bin/tools/crc32.d.ts",
1103
+ "bin/tools/createObjectThatThrowsIfAccessed.d.ts",
1092
1104
  "bin/tools/deflate.d.ts",
1093
1105
  "bin/tools/downloadAndExtractArchive.d.ts",
1094
1106
  "bin/tools/escapeStringForPropertiesFile.d.ts",
@@ -1114,12 +1126,14 @@
1114
1126
  "bin/tools/runPrettier.d.ts",
1115
1127
  "bin/tools/SemVer.d.ts",
1116
1128
  "bin/tools/String.prototype.replaceAll.d.ts",
1129
+ "bin/tools/Stringifyable.d.ts",
1117
1130
  "bin/tools/tee.d.ts",
1118
1131
  "bin/tools/transformCodebase.d.ts",
1119
1132
  "bin/tools/trimIndent.d.ts",
1120
1133
  "bin/tools/untrackFromGit.d.ts",
1121
1134
  "bin/update-kc-gen.d.ts",
1122
1135
  "bin/main.js",
1136
+ "bin/153.index.js",
1123
1137
  "bin/266.index.js",
1124
1138
  "bin/304.index.js",
1125
1139
  "bin/33.index.js",
@@ -1130,10 +1144,8 @@
1130
1144
  "bin/490.index.js",
1131
1145
  "bin/503.index.js",
1132
1146
  "bin/525.index.js",
1133
- "bin/573.index.js",
1134
1147
  "bin/653.index.js",
1135
1148
  "bin/658.index.js",
1136
- "bin/682.index.js",
1137
1149
  "bin/720.index.js",
1138
1150
  "bin/735.index.js",
1139
1151
  "bin/743.index.js",
@@ -1142,6 +1154,7 @@
1142
1154
  "bin/805.index.js",
1143
1155
  "bin/854.index.js",
1144
1156
  "bin/877.index.js",
1157
+ "bin/880.index.js",
1145
1158
  "bin/921.index.js",
1146
1159
  "bin/97.index.js",
1147
1160
  "bin/shared/constants.js",
@@ -40,6 +40,7 @@ import { escapeStringForPropertiesFile } from "../../tools/escapeStringForProper
40
40
  import * as child_process from "child_process";
41
41
  import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
42
42
  import propertiesParser from "properties-parser";
43
+ import { createObjectThatThrowsIfAccessed } from "../../tools/createObjectThatThrowsIfAccessed";
43
44
 
44
45
  export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode &
45
46
  BuildContextLike_generateMessageProperties & {
@@ -256,15 +257,17 @@ export async function generateResources(params: {
256
257
  writeMessagePropertiesFiles;
257
258
  }
258
259
 
259
- bring_in_spas_messages: {
260
+ bring_in_account_spa_messages: {
260
261
  if (!isSpa) {
261
- break bring_in_spas_messages;
262
+ break bring_in_account_spa_messages;
262
263
  }
263
264
 
264
- assert(themeType !== "login");
265
+ if (themeType !== "account") {
266
+ break bring_in_account_spa_messages;
267
+ }
265
268
 
266
269
  const accountUiDirPath = child_process
267
- .execSync(`npm list @keycloakify/keycloak-${themeType}-ui --parseable`, {
270
+ .execSync(`npm list @keycloakify/keycloak-account-ui --parseable`, {
268
271
  cwd: pathDirname(buildContext.packageJsonFilePath)
269
272
  })
270
273
  .toString("utf8")
@@ -279,7 +282,7 @@ export async function generateResources(params: {
279
282
  }
280
283
 
281
284
  const messagesDirPath_dest = pathJoin(
282
- getThemeTypeDirPath({ themeName, themeType }),
285
+ getThemeTypeDirPath({ themeName, themeType: "account" }),
283
286
  "messages"
284
287
  );
285
288
 
@@ -291,7 +294,7 @@ export async function generateResources(params: {
291
294
  apply_theme_changes: {
292
295
  const messagesDirPath_theme = pathJoin(
293
296
  buildContext.themeSrcDirPath,
294
- themeType,
297
+ "account",
295
298
  "messages"
296
299
  );
297
300
 
@@ -339,6 +342,159 @@ export async function generateResources(params: {
339
342
  );
340
343
  }
341
344
 
345
+ bring_in_admin_messages: {
346
+ if (themeType !== "admin") {
347
+ break bring_in_admin_messages;
348
+ }
349
+
350
+ const messagesDirPath_theme = pathJoin(
351
+ buildContext.themeSrcDirPath,
352
+ "admin",
353
+ "i18n"
354
+ );
355
+
356
+ assert(
357
+ fs.existsSync(messagesDirPath_theme),
358
+ `${messagesDirPath_theme} is supposed to exist`
359
+ );
360
+
361
+ const propertiesByLang: Record<
362
+ string,
363
+ {
364
+ base: Buffer;
365
+ override: Buffer | undefined;
366
+ overrideByThemeName: Record<string, Buffer>;
367
+ }
368
+ > = {};
369
+
370
+ fs.readdirSync(messagesDirPath_theme).forEach(basename => {
371
+ type ParsedBasename = { lang: string } & (
372
+ | {
373
+ isOverride: false;
374
+ }
375
+ | {
376
+ isOverride: true;
377
+ themeName: string | undefined;
378
+ }
379
+ );
380
+
381
+ const parsedBasename = ((): ParsedBasename | undefined => {
382
+ const match = basename.match(/^messages_([^.]+)\.properties$/);
383
+
384
+ if (match === null) {
385
+ return undefined;
386
+ }
387
+
388
+ const discriminator = match[1];
389
+
390
+ const split = discriminator.split("_override");
391
+
392
+ if (split.length === 1) {
393
+ return {
394
+ lang: discriminator,
395
+ isOverride: false
396
+ };
397
+ }
398
+
399
+ assert(split.length === 2);
400
+
401
+ if (split[1] === "") {
402
+ return {
403
+ lang: split[0],
404
+ isOverride: true,
405
+ themeName: undefined
406
+ };
407
+ }
408
+
409
+ const match2 = split[1].match(/^_(.+)$/);
410
+
411
+ assert(match2 !== null);
412
+
413
+ return {
414
+ lang: split[0],
415
+ isOverride: true,
416
+ themeName: match2[1]
417
+ };
418
+ })();
419
+
420
+ if (parsedBasename === undefined) {
421
+ return;
422
+ }
423
+
424
+ propertiesByLang[parsedBasename.lang] ??= {
425
+ base: createObjectThatThrowsIfAccessed<Buffer>({
426
+ debugMessage: `No base ${parsedBasename.lang} translation for admin theme`
427
+ }),
428
+ override: undefined,
429
+ overrideByThemeName: {}
430
+ };
431
+
432
+ const buffer = fs.readFileSync(pathJoin(messagesDirPath_theme, basename));
433
+
434
+ if (parsedBasename.isOverride === false) {
435
+ propertiesByLang[parsedBasename.lang].base = buffer;
436
+ return;
437
+ }
438
+
439
+ if (parsedBasename.themeName === undefined) {
440
+ propertiesByLang[parsedBasename.lang].override = buffer;
441
+ return;
442
+ }
443
+
444
+ propertiesByLang[parsedBasename.lang].overrideByThemeName[
445
+ parsedBasename.themeName
446
+ ] = buffer;
447
+ });
448
+
449
+ writeMessagePropertiesFilesByThemeType.admin = ({
450
+ messageDirPath,
451
+ themeName
452
+ }) => {
453
+ if (!fs.existsSync(messageDirPath)) {
454
+ fs.mkdirSync(messageDirPath, { recursive: true });
455
+ }
456
+
457
+ Object.entries(propertiesByLang).forEach(
458
+ ([lang, { base, override, overrideByThemeName }]) => {
459
+ (languageTags ??= []).push(lang);
460
+
461
+ const messages = propertiesParser.parse(base.toString("utf8"));
462
+
463
+ if (override !== undefined) {
464
+ const overrideMessages = propertiesParser.parse(
465
+ override.toString("utf8")
466
+ );
467
+
468
+ Object.entries(overrideMessages).forEach(
469
+ ([key, value]) => (messages[key] = value)
470
+ );
471
+ }
472
+
473
+ if (themeName in overrideByThemeName) {
474
+ const overrideMessages = propertiesParser.parse(
475
+ overrideByThemeName[themeName].toString("utf8")
476
+ );
477
+
478
+ Object.entries(overrideMessages).forEach(
479
+ ([key, value]) => (messages[key] = value)
480
+ );
481
+ }
482
+
483
+ const editor = propertiesParser.createEditor();
484
+
485
+ Object.entries(messages).forEach(([key, value]) => {
486
+ editor.set(key, value);
487
+ });
488
+
489
+ fs.writeFileSync(
490
+ pathJoin(messageDirPath, `messages_${lang}.properties`),
491
+ Buffer.from(editor.toString(), "utf8")
492
+ );
493
+ }
494
+ );
495
+ };
496
+ }
497
+
342
498
  keycloak_static_resources: {
343
499
  if (isSpa) {
344
500
  break keycloak_static_resources;
package/src/bin/main.ts CHANGED
@@ -259,11 +259,12 @@ program
259
259
  .option({
260
260
  key: "file",
261
261
  name: (() => {
262
- const name = "file";
262
+ const long = "file";
263
+ const short = "f";
263
264
 
264
- optionsKeys.push(name);
265
+ optionsKeys.push(long, short);
265
266
 
266
- return name;
267
+ return { long, short };
267
268
  })(),
268
269
  description: [
269
270
  "Relative path of the file relative to the directory of your keycloak theme source",