keycloakify 11.5.4 → 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.
- package/bin/153.index.js +81 -28
- package/bin/356.index.js +48 -25
- package/bin/{573.index.js → 880.index.js} +155 -9
- package/bin/main.js +5 -4
- package/bin/tools/createObjectThatThrowsIfAccessed.d.ts +21 -0
- package/package.json +5 -2
- package/src/bin/keycloakify/generateResources/generateResources.ts +162 -6
- package/src/bin/main.ts +4 -3
- package/src/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts +63 -24
- package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-22.json +2201 -0
- package/src/bin/start-keycloak/start-keycloak.ts +131 -36
- package/src/bin/tools/createObjectThatThrowsIfAccessed.ts +90 -0
@@ -142,15 +142,96 @@ export async function command(params: {
|
|
142
142
|
].join("\n")
|
143
143
|
);
|
144
144
|
|
145
|
-
const
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
145
|
+
const tag_userSelected = await (async () => {
|
146
|
+
let tag: string;
|
147
|
+
|
148
|
+
let latestMajorTags_copy = [...latestMajorTags];
|
149
|
+
|
150
|
+
while (true) {
|
151
|
+
const { value } = await cliSelect<string>({
|
152
|
+
values: latestMajorTags_copy
|
153
|
+
}).catch(() => {
|
154
|
+
process.exit(-1);
|
155
|
+
});
|
156
|
+
|
157
|
+
tag = value;
|
158
|
+
|
159
|
+
{
|
160
|
+
const doImplementAccountMpa =
|
161
|
+
buildContext.implementedThemeTypes.account.isImplemented &&
|
162
|
+
buildContext.implementedThemeTypes.account.type === "Multi-Page";
|
163
|
+
|
164
|
+
if (doImplementAccountMpa && tag.startsWith("22.")) {
|
165
|
+
console.log(
|
166
|
+
chalk.yellow(
|
167
|
+
`You are implementing a Multi-Page Account theme. Keycloak 22 is not supported, select another version`
|
168
|
+
)
|
169
|
+
);
|
170
|
+
latestMajorTags_copy = latestMajorTags_copy.filter(
|
171
|
+
tag => !tag.startsWith("22.")
|
172
|
+
);
|
173
|
+
continue;
|
174
|
+
}
|
175
|
+
}
|
150
176
|
|
151
|
-
|
177
|
+
const readMajor = (tag: string) => {
|
178
|
+
const major = parseInt(tag.split(".")[0]);
|
179
|
+
assert(!isNaN(major));
|
180
|
+
return major;
|
181
|
+
};
|
152
182
|
|
153
|
-
|
183
|
+
{
|
184
|
+
const major = readMajor(tag);
|
185
|
+
|
186
|
+
const doImplementAdminTheme =
|
187
|
+
buildContext.implementedThemeTypes.admin.isImplemented;
|
188
|
+
|
189
|
+
const getIsSupported = (major: number) => major >= 23;
|
190
|
+
|
191
|
+
if (doImplementAdminTheme && !getIsSupported(major)) {
|
192
|
+
console.log(
|
193
|
+
chalk.yellow(
|
194
|
+
`You are implementing an Admin theme. Only Keycloak 23 and later are supported, select another version`
|
195
|
+
)
|
196
|
+
);
|
197
|
+
latestMajorTags_copy = latestMajorTags_copy.filter(tag =>
|
198
|
+
getIsSupported(readMajor(tag))
|
199
|
+
);
|
200
|
+
continue;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
{
|
205
|
+
const doImplementAccountSpa =
|
206
|
+
buildContext.implementedThemeTypes.account.isImplemented &&
|
207
|
+
buildContext.implementedThemeTypes.account.type === "Single-Page";
|
208
|
+
|
209
|
+
const major = readMajor(tag);
|
210
|
+
|
211
|
+
const getIsSupported = (major: number) => major >= 19;
|
212
|
+
|
213
|
+
if (doImplementAccountSpa && !getIsSupported(major)) {
|
214
|
+
console.log(
|
215
|
+
chalk.yellow(
|
216
|
+
`You are implementing a Single-Page Account theme. Only Keycloak 19 and later are supported, select another version`
|
217
|
+
)
|
218
|
+
);
|
219
|
+
latestMajorTags_copy = latestMajorTags_copy.filter(tag =>
|
220
|
+
getIsSupported(readMajor(tag))
|
221
|
+
);
|
222
|
+
continue;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
break;
|
227
|
+
}
|
228
|
+
|
229
|
+
return tag;
|
230
|
+
})();
|
231
|
+
|
232
|
+
console.log(`→ ${tag_userSelected}`);
|
233
|
+
|
234
|
+
return { dockerImageTag: tag_userSelected };
|
154
235
|
})();
|
155
236
|
|
156
237
|
const keycloakMajorVersionNumber = (() => {
|
@@ -623,42 +704,56 @@ export async function command(params: {
|
|
623
704
|
}
|
624
705
|
)
|
625
706
|
.on("all", async (...[, filePath]) => {
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
buildContext.implementedThemeTypes.account.type === "Single-Page";
|
630
|
-
|
631
|
-
if (!doImplementAccountSpa) {
|
632
|
-
break ignore_account_spa;
|
707
|
+
ignore_path_covered_by_hmr: {
|
708
|
+
if (filePath.endsWith(".properties")) {
|
709
|
+
break ignore_path_covered_by_hmr;
|
633
710
|
}
|
634
711
|
|
635
|
-
if (
|
636
|
-
|
637
|
-
dirPath: pathJoin(buildContext.themeSrcDirPath, "account"),
|
638
|
-
filePath
|
639
|
-
})
|
640
|
-
) {
|
641
|
-
break ignore_account_spa;
|
712
|
+
if (!doStartDevServer) {
|
713
|
+
break ignore_path_covered_by_hmr;
|
642
714
|
}
|
643
715
|
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
716
|
+
ignore_account_spa: {
|
717
|
+
const doImplementAccountSpa =
|
718
|
+
buildContext.implementedThemeTypes.account.isImplemented &&
|
719
|
+
buildContext.implementedThemeTypes.account.type ===
|
720
|
+
"Single-Page";
|
721
|
+
|
722
|
+
if (!doImplementAccountSpa) {
|
723
|
+
break ignore_account_spa;
|
724
|
+
}
|
725
|
+
|
726
|
+
if (
|
727
|
+
!isInside({
|
728
|
+
dirPath: pathJoin(
|
729
|
+
buildContext.themeSrcDirPath,
|
730
|
+
"account"
|
731
|
+
),
|
732
|
+
filePath
|
733
|
+
})
|
734
|
+
) {
|
735
|
+
break ignore_account_spa;
|
736
|
+
}
|
737
|
+
|
738
|
+
return;
|
650
739
|
}
|
651
740
|
|
652
|
-
|
653
|
-
!
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
741
|
+
ignore_admin: {
|
742
|
+
if (!buildContext.implementedThemeTypes.admin.isImplemented) {
|
743
|
+
break ignore_admin;
|
744
|
+
}
|
745
|
+
|
746
|
+
if (
|
747
|
+
!isInside({
|
748
|
+
dirPath: pathJoin(buildContext.themeSrcDirPath, "admin"),
|
749
|
+
filePath
|
750
|
+
})
|
751
|
+
) {
|
752
|
+
break ignore_admin;
|
753
|
+
}
|
754
|
+
|
755
|
+
return;
|
659
756
|
}
|
660
|
-
|
661
|
-
return;
|
662
757
|
}
|
663
758
|
|
664
759
|
console.log(`Detected changes in ${filePath}`);
|
@@ -0,0 +1,90 @@
|
|
1
|
+
const keyIsTrapped = "isTrapped_zSskDe9d";
|
2
|
+
|
3
|
+
export class AccessError extends Error {
|
4
|
+
constructor(message: string) {
|
5
|
+
super(message);
|
6
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
export function createObjectThatThrowsIfAccessed<T extends object>(params?: {
|
11
|
+
debugMessage?: string;
|
12
|
+
isPropertyWhitelisted?: (prop: string | number | symbol) => boolean;
|
13
|
+
}): T {
|
14
|
+
const { debugMessage = "", isPropertyWhitelisted = () => false } = params ?? {};
|
15
|
+
|
16
|
+
const get: NonNullable<ProxyHandler<T>["get"]> = (...args) => {
|
17
|
+
const [, prop] = args;
|
18
|
+
|
19
|
+
if (isPropertyWhitelisted(prop)) {
|
20
|
+
return Reflect.get(...args);
|
21
|
+
}
|
22
|
+
|
23
|
+
if (prop === keyIsTrapped) {
|
24
|
+
return true;
|
25
|
+
}
|
26
|
+
|
27
|
+
throw new AccessError(`Cannot access ${String(prop)} yet ${debugMessage}`);
|
28
|
+
};
|
29
|
+
|
30
|
+
const trappedObject = new Proxy<T>({} as any, {
|
31
|
+
get,
|
32
|
+
set: get
|
33
|
+
});
|
34
|
+
|
35
|
+
return trappedObject;
|
36
|
+
}
|
37
|
+
|
38
|
+
export function createObjectThatThrowsIfAccessedFactory(params: {
|
39
|
+
isPropertyWhitelisted?: (prop: string | number | symbol) => boolean;
|
40
|
+
}) {
|
41
|
+
const { isPropertyWhitelisted } = params;
|
42
|
+
|
43
|
+
return {
|
44
|
+
createObjectThatThrowsIfAccessed: <T extends object>(params?: {
|
45
|
+
debugMessage?: string;
|
46
|
+
}) => {
|
47
|
+
const { debugMessage } = params ?? {};
|
48
|
+
|
49
|
+
return createObjectThatThrowsIfAccessed<T>({
|
50
|
+
debugMessage,
|
51
|
+
isPropertyWhitelisted
|
52
|
+
});
|
53
|
+
}
|
54
|
+
};
|
55
|
+
}
|
56
|
+
|
57
|
+
export function isObjectThatThrowIfAccessed(obj: object) {
|
58
|
+
return (obj as any)[keyIsTrapped] === true;
|
59
|
+
}
|
60
|
+
|
61
|
+
export const THROW_IF_ACCESSED = {
|
62
|
+
__brand: "THROW_IF_ACCESSED"
|
63
|
+
};
|
64
|
+
|
65
|
+
export function createObjectWithSomePropertiesThatThrowIfAccessed<
|
66
|
+
T extends Record<string, unknown>
|
67
|
+
>(obj: { [K in keyof T]: T[K] | typeof THROW_IF_ACCESSED }, debugMessage?: string): T {
|
68
|
+
return Object.defineProperties(
|
69
|
+
obj,
|
70
|
+
Object.fromEntries(
|
71
|
+
Object.entries(obj)
|
72
|
+
.filter(([, value]) => value === THROW_IF_ACCESSED)
|
73
|
+
.map(([key]) => {
|
74
|
+
const getAndSet = () => {
|
75
|
+
throw new AccessError(
|
76
|
+
`Cannot access ${key} yet ${debugMessage ?? ""}`
|
77
|
+
);
|
78
|
+
};
|
79
|
+
|
80
|
+
const pd = {
|
81
|
+
get: getAndSet,
|
82
|
+
set: getAndSet,
|
83
|
+
enumerable: true
|
84
|
+
};
|
85
|
+
|
86
|
+
return [key, pd];
|
87
|
+
})
|
88
|
+
)
|
89
|
+
) as any;
|
90
|
+
}
|