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
@@ -0,0 +1,164 @@
1
+ import { getIsAtomic, getValueAtPath, type Stringifyable } from "./Stringifyable";
2
+
3
+ export function canonicalStringify(params: {
4
+ data: Record<string, Stringifyable> | Stringifyable[];
5
+ referenceData: Record<string, Stringifyable> | Stringifyable[];
6
+ }): string {
7
+ const { data, referenceData } = params;
8
+
9
+ return JSON.stringify(
10
+ makeDeterministicCopy({
11
+ path: [],
12
+ data,
13
+ getCanonicalKeys: path => {
14
+ const referenceValue = (() => {
15
+ const path_patched: (string | number)[] = [];
16
+
17
+ for (let i = 0; i < path.length; i++) {
18
+ let value_i = getValueAtPath(referenceData, [
19
+ ...path_patched,
20
+ path[i]
21
+ ]);
22
+
23
+ if (value_i !== undefined) {
24
+ path_patched.push(path[i]);
25
+ continue;
26
+ }
27
+
28
+ if (typeof path[i] !== "number") {
29
+ return undefined;
30
+ }
31
+
32
+ value_i = getValueAtPath(referenceData, [...path_patched, 0]);
33
+
34
+ if (value_i !== undefined) {
35
+ path_patched.push(0);
36
+ continue;
37
+ }
38
+
39
+ return undefined;
40
+ }
41
+
42
+ return getValueAtPath(referenceData, path_patched);
43
+ })();
44
+
45
+ if (referenceValue === undefined) {
46
+ return undefined;
47
+ }
48
+
49
+ if (getIsAtomic(referenceValue)) {
50
+ return undefined;
51
+ }
52
+
53
+ if (referenceValue instanceof Array) {
54
+ return undefined;
55
+ }
56
+
57
+ return Object.keys(referenceValue);
58
+ }
59
+ }),
60
+ null,
61
+ 2
62
+ );
63
+ }
64
+
65
+ function makeDeterministicCopy(params: {
66
+ path: (string | number)[];
67
+ data: Stringifyable;
68
+ getCanonicalKeys: (path: (string | number)[]) => string[] | undefined;
69
+ }): Stringifyable {
70
+ const { path, data, getCanonicalKeys } = params;
71
+
72
+ if (getIsAtomic(data)) {
73
+ return data;
74
+ }
75
+
76
+ if (data instanceof Array) {
77
+ return makeDeterministicCopy_array({
78
+ path,
79
+ data,
80
+ getCanonicalKeys
81
+ });
82
+ }
83
+
84
+ return makeDeterministicCopy_record({
85
+ path,
86
+ data,
87
+ getCanonicalKeys
88
+ });
89
+ }
90
+
91
+ function makeDeterministicCopy_record(params: {
92
+ path: (string | number)[];
93
+ data: Record<string, Stringifyable>;
94
+ getCanonicalKeys: (path: (string | number)[]) => string[] | undefined;
95
+ }): Record<string, Stringifyable> {
96
+ const { path, data, getCanonicalKeys } = params;
97
+
98
+ const keysOfAtomicValues: string[] = [];
99
+ const keysOfNonAtomicValues: string[] = [];
100
+
101
+ for (const [key, value] of Object.entries(data)) {
102
+ if (getIsAtomic(value)) {
103
+ keysOfAtomicValues.push(key);
104
+ } else {
105
+ keysOfNonAtomicValues.push(key);
106
+ }
107
+ }
108
+
109
+ keysOfAtomicValues.sort();
110
+ keysOfNonAtomicValues.sort();
111
+
112
+ const keys = [...keysOfAtomicValues, ...keysOfNonAtomicValues];
113
+
114
+ reorder_according_to_canonical: {
115
+ const canonicalKeys = getCanonicalKeys(path);
116
+
117
+ if (canonicalKeys === undefined) {
118
+ break reorder_according_to_canonical;
119
+ }
120
+
121
+ const keys_toPrepend: string[] = [];
122
+
123
+ for (const key of canonicalKeys) {
124
+ const indexOfKey = keys.indexOf(key);
125
+
126
+ if (indexOfKey === -1) {
127
+ continue;
128
+ }
129
+
130
+ keys.splice(indexOfKey, 1);
131
+ keys_toPrepend.push(key);
132
+ }
133
+
134
+ keys.unshift(...keys_toPrepend);
135
+ }
136
+
137
+ const result: Record<string, Stringifyable> = {};
138
+
139
+ for (const key of keys) {
140
+ result[key] = makeDeterministicCopy({
141
+ path: [...path, key],
142
+ data: data[key],
143
+ getCanonicalKeys
144
+ });
145
+ }
146
+
147
+ return result;
148
+ }
149
+
150
+ function makeDeterministicCopy_array(params: {
151
+ path: (string | number)[];
152
+ data: Stringifyable[];
153
+ getCanonicalKeys: (path: (string | number)[]) => string[] | undefined;
154
+ }): Stringifyable[] {
155
+ const { path, data, getCanonicalKeys } = params;
156
+
157
+ return [...data].map((entry, i) =>
158
+ makeDeterministicCopy({
159
+ path: [...path, i],
160
+ data: entry,
161
+ getCanonicalKeys
162
+ })
163
+ );
164
+ }
@@ -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
+ }