keycloakify 11.4.5 → 11.5.1

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 (44) hide show
  1. package/bin/375.index.js +4089 -0
  2. package/bin/{20.index.js → 490.index.js} +378 -56
  3. package/bin/{36.index.js → 503.index.js} +53 -2
  4. package/bin/{450.index.js → 525.index.js} +2 -4085
  5. package/bin/653.index.js +108 -110
  6. package/bin/682.index.js +1987 -0
  7. package/bin/735.index.js +107 -109
  8. package/bin/921.index.js +1 -1
  9. package/bin/main.js +8 -2
  10. package/bin/shared/constants.d.ts +3 -0
  11. package/bin/shared/constants.js +3 -0
  12. package/bin/shared/constants.js.map +1 -1
  13. package/bin/start-keycloak/getSupportedDockerImageTags.d.ts +8 -0
  14. package/bin/start-keycloak/realmConfig/ParsedRealmJson.d.ts +45 -0
  15. package/bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.d.ts +8 -0
  16. package/bin/start-keycloak/realmConfig/defaultConfig/index.d.ts +1 -0
  17. package/bin/start-keycloak/realmConfig/dumpContainerConfig.d.ts +9 -0
  18. package/bin/start-keycloak/realmConfig/index.d.ts +1 -0
  19. package/bin/start-keycloak/realmConfig/prepareRealmConfig.d.ts +15 -0
  20. package/bin/start-keycloak/realmConfig/realmConfig.d.ts +16 -0
  21. package/package.json +31 -14
  22. package/src/bin/shared/constants.ts +6 -0
  23. package/src/bin/start-keycloak/getSupportedDockerImageTags.ts +230 -0
  24. package/src/bin/start-keycloak/keycloakify-logging-1.0.3.jar +0 -0
  25. package/src/bin/start-keycloak/realmConfig/ParsedRealmJson.ts +136 -0
  26. package/src/bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.ts +75 -0
  27. package/src/bin/start-keycloak/realmConfig/defaultConfig/index.ts +1 -0
  28. package/src/bin/start-keycloak/{myrealm-realm-18.json → realmConfig/defaultConfig/realm-kc-18.json} +123 -60
  29. package/src/bin/start-keycloak/{myrealm-realm-19.json → realmConfig/defaultConfig/realm-kc-19.json} +81 -41
  30. package/src/bin/start-keycloak/{myrealm-realm-20.json → realmConfig/defaultConfig/realm-kc-20.json} +83 -42
  31. package/src/bin/start-keycloak/{myrealm-realm-21.json → realmConfig/defaultConfig/realm-kc-21.json} +58 -17
  32. package/src/bin/start-keycloak/{myrealm-realm-23.json → realmConfig/defaultConfig/realm-kc-23.json} +64 -20
  33. package/src/bin/start-keycloak/{myrealm-realm-24.json → realmConfig/defaultConfig/realm-kc-24.json} +63 -19
  34. package/src/bin/start-keycloak/{myrealm-realm-25.json → realmConfig/defaultConfig/realm-kc-25.json} +75 -20
  35. package/src/bin/start-keycloak/{myrealm-realm-26.json → realmConfig/defaultConfig/realm-kc-26.json} +103 -19
  36. package/src/bin/start-keycloak/realmConfig/dumpContainerConfig.ts +194 -0
  37. package/src/bin/start-keycloak/realmConfig/index.ts +1 -0
  38. package/src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts +365 -0
  39. package/src/bin/start-keycloak/realmConfig/realmConfig.ts +159 -0
  40. package/src/bin/start-keycloak/start-keycloak.ts +160 -184
  41. package/src/bin/start-keycloak/startViteDevServer.ts +1 -0
  42. package/vite-plugin/index.js +6 -0
  43. package/bin/392.index.js +0 -740
  44. package/bin/932.index.js +0 -327
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "11.4.5",
3
+ "version": "11.5.1",
4
4
  "description": "Framework to create custom Keycloak UIs",
5
5
  "repository": {
6
6
  "type": "git",
@@ -700,16 +700,25 @@
700
700
  "src/bin/shared/metaInfKeycloakThemes.ts",
701
701
  "src/bin/shared/promptKeycloakVersion.ts",
702
702
  "src/bin/start-keycloak/appBuild.ts",
703
+ "src/bin/start-keycloak/getSupportedDockerImageTags.ts",
703
704
  "src/bin/start-keycloak/index.ts",
705
+ "src/bin/start-keycloak/keycloakify-logging-1.0.3.jar",
704
706
  "src/bin/start-keycloak/keycloakifyBuild.ts",
705
- "src/bin/start-keycloak/myrealm-realm-18.json",
706
- "src/bin/start-keycloak/myrealm-realm-19.json",
707
- "src/bin/start-keycloak/myrealm-realm-20.json",
708
- "src/bin/start-keycloak/myrealm-realm-21.json",
709
- "src/bin/start-keycloak/myrealm-realm-23.json",
710
- "src/bin/start-keycloak/myrealm-realm-24.json",
711
- "src/bin/start-keycloak/myrealm-realm-25.json",
712
- "src/bin/start-keycloak/myrealm-realm-26.json",
707
+ "src/bin/start-keycloak/realmConfig/ParsedRealmJson.ts",
708
+ "src/bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.ts",
709
+ "src/bin/start-keycloak/realmConfig/defaultConfig/index.ts",
710
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-18.json",
711
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-19.json",
712
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-20.json",
713
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-21.json",
714
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-23.json",
715
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-24.json",
716
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-25.json",
717
+ "src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-26.json",
718
+ "src/bin/start-keycloak/realmConfig/dumpContainerConfig.ts",
719
+ "src/bin/start-keycloak/realmConfig/index.ts",
720
+ "src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts",
721
+ "src/bin/start-keycloak/realmConfig/realmConfig.ts",
713
722
  "src/bin/start-keycloak/start-keycloak.ts",
714
723
  "src/bin/start-keycloak/startViteDevServer.ts",
715
724
  "src/bin/tools/OptionalIfCanBeUndefined.ts",
@@ -1064,8 +1073,16 @@
1064
1073
  "bin/shared/metaInfKeycloakThemes.d.ts",
1065
1074
  "bin/shared/promptKeycloakVersion.d.ts",
1066
1075
  "bin/start-keycloak/appBuild.d.ts",
1076
+ "bin/start-keycloak/getSupportedDockerImageTags.d.ts",
1067
1077
  "bin/start-keycloak/index.d.ts",
1068
1078
  "bin/start-keycloak/keycloakifyBuild.d.ts",
1079
+ "bin/start-keycloak/realmConfig/defaultConfig/defaultConfig.d.ts",
1080
+ "bin/start-keycloak/realmConfig/defaultConfig/index.d.ts",
1081
+ "bin/start-keycloak/realmConfig/dumpContainerConfig.d.ts",
1082
+ "bin/start-keycloak/realmConfig/index.d.ts",
1083
+ "bin/start-keycloak/realmConfig/ParsedRealmJson.d.ts",
1084
+ "bin/start-keycloak/realmConfig/prepareRealmConfig.d.ts",
1085
+ "bin/start-keycloak/realmConfig/realmConfig.d.ts",
1069
1086
  "bin/start-keycloak/start-keycloak.d.ts",
1070
1087
  "bin/start-keycloak/startViteDevServer.d.ts",
1071
1088
  "bin/tools/assertNoPnpmDlx.d.ts",
@@ -1103,19 +1120,20 @@
1103
1120
  "bin/tools/untrackFromGit.d.ts",
1104
1121
  "bin/update-kc-gen.d.ts",
1105
1122
  "bin/main.js",
1106
- "bin/20.index.js",
1107
1123
  "bin/266.index.js",
1108
1124
  "bin/304.index.js",
1109
1125
  "bin/33.index.js",
1110
1126
  "bin/356.index.js",
1111
- "bin/36.index.js",
1112
- "bin/392.index.js",
1127
+ "bin/375.index.js",
1113
1128
  "bin/40.index.js",
1114
- "bin/450.index.js",
1115
1129
  "bin/453.index.js",
1130
+ "bin/490.index.js",
1131
+ "bin/503.index.js",
1132
+ "bin/525.index.js",
1116
1133
  "bin/573.index.js",
1117
1134
  "bin/653.index.js",
1118
1135
  "bin/658.index.js",
1136
+ "bin/682.index.js",
1119
1137
  "bin/720.index.js",
1120
1138
  "bin/735.index.js",
1121
1139
  "bin/743.index.js",
@@ -1125,7 +1143,6 @@
1125
1143
  "bin/854.index.js",
1126
1144
  "bin/877.index.js",
1127
1145
  "bin/921.index.js",
1128
- "bin/932.index.js",
1129
1146
  "bin/97.index.js",
1130
1147
  "bin/shared/constants.js",
1131
1148
  "bin/shared/constants.js.map",
@@ -81,3 +81,9 @@ export const CUSTOM_HANDLER_ENV_NAMES = {
81
81
  export const KEYCLOAK_THEME = "keycloak-theme";
82
82
 
83
83
  export const KEYCLOAKIFY_SPA_DEV_SERVER_PORT = "KEYCLOAKIFY_SPA_DEV_SERVER_PORT";
84
+
85
+ export const KEYCLOAKIFY_LOGGING_VERSION = "1.0.3";
86
+
87
+ export const KEYCLOAKIFY_LOGIN_JAR_BASENAME = `keycloakify-logging-${KEYCLOAKIFY_LOGGING_VERSION}.jar`;
88
+
89
+ export const TEST_APP_URL = "https://my-theme.keycloakify.dev";
@@ -0,0 +1,230 @@
1
+ import fetch from "make-fetch-happen";
2
+ import type { BuildContext } from "../shared/buildContext";
3
+ import { assert, type Equals } from "tsafe/assert";
4
+ import { id } from "tsafe/id";
5
+ import { z } from "zod";
6
+ import { SemVer } from "../tools/SemVer";
7
+ import { exclude } from "tsafe/exclude";
8
+ import { getSupportedKeycloakMajorVersions } from "./realmConfig/defaultConfig";
9
+ import { join as pathJoin, dirname as pathDirname } from "path";
10
+ import * as fs from "fs/promises";
11
+ import { existsAsync } from "../tools/fs.existsAsync";
12
+ import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
13
+
14
+ export type BuildContextLike = {
15
+ fetchOptions: BuildContext["fetchOptions"];
16
+ cacheDirPath: string;
17
+ };
18
+
19
+ assert<BuildContext extends BuildContextLike ? true : false>;
20
+
21
+ export async function getSupportedDockerImageTags(params: {
22
+ buildContext: BuildContextLike;
23
+ }) {
24
+ const { buildContext } = params;
25
+
26
+ {
27
+ const result = await getCachedValue({ cacheDirPath: buildContext.cacheDirPath });
28
+
29
+ if (result !== undefined) {
30
+ return result;
31
+ }
32
+ }
33
+
34
+ const tags: string[] = [];
35
+
36
+ await (async function callee(url: string) {
37
+ const r = await fetch(url, buildContext.fetchOptions);
38
+
39
+ await Promise.all([
40
+ (async () => {
41
+ tags.push(
42
+ ...z
43
+ .object({
44
+ tags: z.array(z.string())
45
+ })
46
+ .parse(await r.json()).tags
47
+ );
48
+ })(),
49
+ (async () => {
50
+ const link = r.headers.get("link");
51
+
52
+ if (link === null) {
53
+ return;
54
+ }
55
+
56
+ const split = link.split(";").map(s => s.trim());
57
+
58
+ assert(split.length === 2);
59
+
60
+ assert(split[1] === 'rel="next"');
61
+
62
+ const match = split[0].match(/^<(.+)>$/);
63
+
64
+ assert(match !== null);
65
+
66
+ const nextUrl = new URL(url).origin + match[1];
67
+
68
+ await callee(nextUrl);
69
+ })()
70
+ ]);
71
+ })("https://quay.io/v2/keycloak/keycloak/tags/list");
72
+
73
+ const arr = tags
74
+ .map(tag => ({
75
+ tag,
76
+ version: (() => {
77
+ if (tag.includes("-")) {
78
+ return undefined;
79
+ }
80
+
81
+ let version: SemVer;
82
+
83
+ try {
84
+ version = SemVer.parse(tag);
85
+ } catch {
86
+ return undefined;
87
+ }
88
+
89
+ return version;
90
+ })()
91
+ }))
92
+ .map(({ tag, version }) => (version === undefined ? undefined : { tag, version }))
93
+ .filter(exclude(undefined));
94
+
95
+ const versionByMajor: Record<number, SemVer | undefined> = {};
96
+
97
+ for (const { version } of arr) {
98
+ const version_current = versionByMajor[version.major];
99
+
100
+ if (
101
+ version_current === undefined ||
102
+ SemVer.compare(version_current, version) === -1
103
+ ) {
104
+ versionByMajor[version.major] = version;
105
+ }
106
+ }
107
+
108
+ const supportedKeycloakMajorVersions = getSupportedKeycloakMajorVersions();
109
+
110
+ const result = Object.entries(versionByMajor)
111
+ .sort(([a], [b]) => parseInt(b) - parseInt(a))
112
+ .map(([, version]) => version)
113
+ .map(version => {
114
+ assert(version !== undefined);
115
+
116
+ if (!supportedKeycloakMajorVersions.includes(version.major)) {
117
+ return undefined;
118
+ }
119
+
120
+ return SemVer.stringify(version);
121
+ })
122
+ .filter(exclude(undefined));
123
+
124
+ await setCachedValue({ cacheDirPath: buildContext.cacheDirPath, result });
125
+
126
+ return result;
127
+ }
128
+
129
+ const { getCachedValue, setCachedValue } = (() => {
130
+ type Cache = {
131
+ keycloakifyVersion: string;
132
+ time: number;
133
+ result: string[];
134
+ };
135
+
136
+ const zCache = (() => {
137
+ type TargetType = Cache;
138
+
139
+ const zTargetType = z.object({
140
+ keycloakifyVersion: z.string(),
141
+ time: z.number(),
142
+ result: z.array(z.string())
143
+ });
144
+
145
+ type InferredType = z.infer<typeof zTargetType>;
146
+
147
+ assert<Equals<TargetType, InferredType>>;
148
+
149
+ return id<z.ZodType<TargetType>>(zTargetType);
150
+ })();
151
+
152
+ let inMemoryCachedResult: Cache["result"] | undefined = undefined;
153
+
154
+ function getCacheFilePath(params: { cacheDirPath: string }) {
155
+ const { cacheDirPath } = params;
156
+
157
+ return pathJoin(cacheDirPath, "supportedDockerImageTags.json");
158
+ }
159
+
160
+ async function getCachedValue(params: { cacheDirPath: string }) {
161
+ const { cacheDirPath } = params;
162
+
163
+ if (inMemoryCachedResult !== undefined) {
164
+ return inMemoryCachedResult;
165
+ }
166
+
167
+ const cacheFilePath = getCacheFilePath({ cacheDirPath });
168
+
169
+ if (!(await existsAsync(cacheFilePath))) {
170
+ return undefined;
171
+ }
172
+
173
+ let cache: Cache | undefined;
174
+
175
+ try {
176
+ cache = zCache.parse(JSON.parse(await fs.readFile(cacheFilePath, "utf8")));
177
+ } catch {
178
+ return undefined;
179
+ }
180
+
181
+ if (cache.keycloakifyVersion !== readThisNpmPackageVersion()) {
182
+ return undefined;
183
+ }
184
+
185
+ if (Date.now() - cache.time > 3_600 * 24) {
186
+ return undefined;
187
+ }
188
+
189
+ inMemoryCachedResult = cache.result;
190
+
191
+ return cache.result;
192
+ }
193
+
194
+ async function setCachedValue(params: {
195
+ cacheDirPath: string;
196
+ result: Cache["result"];
197
+ }) {
198
+ const { cacheDirPath, result } = params;
199
+
200
+ inMemoryCachedResult = result;
201
+
202
+ const cacheFilePath = getCacheFilePath({ cacheDirPath });
203
+
204
+ {
205
+ const dirPath = pathDirname(cacheFilePath);
206
+
207
+ if (!(await existsAsync(dirPath))) {
208
+ await fs.mkdir(dirPath, { recursive: true });
209
+ }
210
+ }
211
+
212
+ await fs.writeFile(
213
+ cacheFilePath,
214
+ JSON.stringify(
215
+ zCache.parse({
216
+ keycloakifyVersion: readThisNpmPackageVersion(),
217
+ time: Date.now(),
218
+ result
219
+ }),
220
+ null,
221
+ 2
222
+ )
223
+ );
224
+ }
225
+
226
+ return {
227
+ getCachedValue,
228
+ setCachedValue
229
+ };
230
+ })();
@@ -0,0 +1,136 @@
1
+ import { z } from "zod";
2
+ import { assert, type Equals } from "tsafe/assert";
3
+ import { is } from "tsafe/is";
4
+ import { id } from "tsafe/id";
5
+ import * as fs from "fs";
6
+
7
+ export type ParsedRealmJson = {
8
+ realm: string;
9
+ loginTheme?: string;
10
+ accountTheme?: string;
11
+ adminTheme?: string;
12
+ emailTheme?: string;
13
+ eventsListeners: string[];
14
+ users: {
15
+ id: string;
16
+ email: string;
17
+ username: string;
18
+ credentials: {
19
+ type: string /* "password" or something else */;
20
+ }[];
21
+ clientRoles?: Record<string, string[]>;
22
+ }[];
23
+ roles: {
24
+ client: Record<
25
+ string,
26
+ {
27
+ name: string;
28
+ containerId: string; // client id
29
+ }[]
30
+ >;
31
+ };
32
+ clients: {
33
+ id: string;
34
+ clientId: string; // example: realm-management
35
+ baseUrl?: string;
36
+ redirectUris?: string[];
37
+ webOrigins?: string[];
38
+ attributes?: {
39
+ "post.logout.redirect.uris"?: string;
40
+ };
41
+ protocol?: string;
42
+ protocolMappers?: {
43
+ id: string;
44
+ name: string;
45
+ protocol: string; // "openid-connect" or something else
46
+ protocolMapper: string; // "oidc-hardcoded-claim-mapper" or something else
47
+ consentRequired: boolean;
48
+ config?: Record<string, string>;
49
+ }[];
50
+ }[];
51
+ };
52
+
53
+ const zParsedRealmJson = (() => {
54
+ type TargetType = ParsedRealmJson;
55
+
56
+ const zTargetType = z.object({
57
+ realm: z.string(),
58
+ loginTheme: z.string().optional(),
59
+ accountTheme: z.string().optional(),
60
+ adminTheme: z.string().optional(),
61
+ emailTheme: z.string().optional(),
62
+ eventsListeners: z.array(z.string()),
63
+ users: z.array(
64
+ z.object({
65
+ id: z.string(),
66
+ email: z.string(),
67
+ username: z.string(),
68
+ credentials: z.array(
69
+ z.object({
70
+ type: z.string()
71
+ })
72
+ ),
73
+ clientRoles: z.record(z.array(z.string())).optional()
74
+ })
75
+ ),
76
+ roles: z.object({
77
+ client: z.record(
78
+ z.array(
79
+ z.object({
80
+ name: z.string(),
81
+ containerId: z.string()
82
+ })
83
+ )
84
+ )
85
+ }),
86
+ clients: z.array(
87
+ z.object({
88
+ id: z.string(),
89
+ clientId: z.string(),
90
+ baseUrl: z.string().optional(),
91
+ redirectUris: z.array(z.string()).optional(),
92
+ webOrigins: z.array(z.string()).optional(),
93
+ attributes: z
94
+ .object({
95
+ "post.logout.redirect.uris": z.string().optional()
96
+ })
97
+ .optional(),
98
+ protocol: z.string().optional(),
99
+ protocolMappers: z
100
+ .array(
101
+ z.object({
102
+ id: z.string(),
103
+ name: z.string(),
104
+ protocol: z.string(),
105
+ protocolMapper: z.string(),
106
+ consentRequired: z.boolean(),
107
+ config: z.record(z.string()).optional()
108
+ })
109
+ )
110
+ .optional()
111
+ })
112
+ )
113
+ });
114
+
115
+ type InferredType = z.infer<typeof zTargetType>;
116
+
117
+ assert<Equals<TargetType, InferredType>>;
118
+
119
+ return id<z.ZodType<TargetType>>(zTargetType);
120
+ })();
121
+
122
+ export function readRealmJsonFile(params: {
123
+ realmJsonFilePath: string;
124
+ }): ParsedRealmJson {
125
+ const { realmJsonFilePath } = params;
126
+
127
+ const parsedRealmJson = JSON.parse(
128
+ fs.readFileSync(realmJsonFilePath).toString("utf8")
129
+ ) as unknown;
130
+
131
+ zParsedRealmJson.parse(parsedRealmJson);
132
+
133
+ assert(is<ParsedRealmJson>(parsedRealmJson));
134
+
135
+ return parsedRealmJson;
136
+ }
@@ -0,0 +1,75 @@
1
+ import { join as pathJoin, dirname as pathDirname } from "path";
2
+ import { getThisCodebaseRootDirPath } from "../../../tools/getThisCodebaseRootDirPath";
3
+ import * as fs from "fs";
4
+ import { exclude } from "tsafe/exclude";
5
+ import { assert } from "tsafe/assert";
6
+ import { type ParsedRealmJson, readRealmJsonFile } from "../ParsedRealmJson";
7
+
8
+ export function getDefaultRealmJsonFilePath(params: {
9
+ keycloakMajorVersionNumber: number;
10
+ }) {
11
+ const { keycloakMajorVersionNumber } = params;
12
+
13
+ return pathJoin(
14
+ getThisCodebaseRootDirPath(),
15
+ "src",
16
+ "bin",
17
+ "start-keycloak",
18
+ "realmConfig",
19
+ "defaultConfig",
20
+ `realm-kc-${keycloakMajorVersionNumber}.json`
21
+ );
22
+ }
23
+
24
+ export const { getSupportedKeycloakMajorVersions } = (() => {
25
+ let cache: number[] | undefined = undefined;
26
+
27
+ function getSupportedKeycloakMajorVersions(): number[] {
28
+ if (cache !== undefined) {
29
+ return cache;
30
+ }
31
+
32
+ cache = fs
33
+ .readdirSync(
34
+ pathDirname(
35
+ getDefaultRealmJsonFilePath({ keycloakMajorVersionNumber: 0 })
36
+ )
37
+ )
38
+ .map(fileBasename => {
39
+ const match = fileBasename.match(/^realm-kc-(\d+)\.json$/);
40
+
41
+ if (match === null) {
42
+ return undefined;
43
+ }
44
+
45
+ const n = parseInt(match[1]);
46
+
47
+ assert(!isNaN(n));
48
+
49
+ return n;
50
+ })
51
+ .filter(exclude(undefined))
52
+ .sort((a, b) => b - a);
53
+
54
+ return cache;
55
+ }
56
+
57
+ return { getSupportedKeycloakMajorVersions };
58
+ })();
59
+
60
+ export function getDefaultConfig(params: {
61
+ keycloakMajorVersionNumber: number;
62
+ }): ParsedRealmJson {
63
+ const { keycloakMajorVersionNumber } = params;
64
+
65
+ assert(
66
+ getSupportedKeycloakMajorVersions().includes(keycloakMajorVersionNumber),
67
+ `We do not have a default config for Keycloak ${keycloakMajorVersionNumber}`
68
+ );
69
+
70
+ return readRealmJsonFile({
71
+ realmJsonFilePath: getDefaultRealmJsonFilePath({
72
+ keycloakMajorVersionNumber
73
+ })
74
+ });
75
+ }
@@ -0,0 +1 @@
1
+ export * from "./defaultConfig";