Fix zod schema error

This commit is contained in:
Joseph Garrone 2024-12-15 11:34:41 +01:00
parent dc942aa5de
commit db0ec954df
3 changed files with 69 additions and 187 deletions

View File

@ -1,123 +0,0 @@
import { z } from "zod";
import { assert, type Equals } from "tsafe/assert";
import { is } from "tsafe/is";
import { id } from "tsafe/id";
import * as fs from "fs";
import { join as pathJoin } from "path";
import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath";
export type ParsedRealmJson = {
name: string;
users: {
id: string;
email: string;
username: string;
attributes: Record<string, unknown>;
credentials: {
type: string /* "password" or something else */;
}[];
clientRoles: Record<string, string[]>;
}[];
roles: {
client: {
name: string;
containerId: string; // client id
}[];
};
clients: {
id: string;
clientId: string; // example: realm-management
baseUrl?: string;
redirectUris?: string[];
webOrigins?: string[];
attributes?: {
"post.logout.redirect.uris"?: string;
};
protocol?: string;
protocolMappers?: unknown[];
}[];
};
export function readRealmJsonFile(params: {
realmJsonFilePath: string;
}): ParsedRealmJson {
const { realmJsonFilePath } = params;
const parsedRealmJson = JSON.parse(
fs.readFileSync(realmJsonFilePath).toString("utf8")
) as unknown;
const zParsedRealmJson = (() => {
type TargetType = ParsedRealmJson;
const zTargetType = z.object({
name: z.string(),
users: z.array(
z.object({
id: z.string(),
email: z.string(),
username: z.string(),
attributes: z.record(z.unknown()),
credentials: z.array(
z.object({
type: z.string()
})
),
clientRoles: z.record(z.array(z.string()))
})
),
roles: z.object({
client: z.array(
z.object({
name: z.string(),
containerId: z.string()
})
)
}),
clients: z.array(
z.object({
id: z.string(),
clientId: z.string(),
baseUrl: z.string().optional(),
redirectUris: z.array(z.string()).optional(),
webOrigins: z.array(z.string()).optional(),
attributes: z
.object({
"post.logout.redirect.uris": z.string().optional()
})
.optional(),
protocol: z.string().optional(),
protocolMappers: z.array(z.unknown()).optional()
})
)
});
type InferredType = z.infer<typeof zTargetType>;
assert<Equals<TargetType, InferredType>>;
return id<z.ZodType<TargetType>>(zTargetType);
})();
zParsedRealmJson.parse(parsedRealmJson);
assert(is<ParsedRealmJson>(parsedRealmJson));
return parsedRealmJson;
}
export function getDefaultConfig(params: {
keycloakMajorVersionNumber: number;
}): ParsedRealmJson {
const { keycloakMajorVersionNumber } = params;
const realmJsonFilePath = pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"start-keycloak",
`myrealm-realm-${keycloakMajorVersionNumber}.json`
);
return readRealmJsonFile({ realmJsonFilePath });
}

View File

@ -5,7 +5,7 @@ import { id } from "tsafe/id";
import * as fs from "fs";
export type ParsedRealmJson = {
name: string;
realm: string;
loginTheme?: string;
accountTheme?: string;
adminTheme?: string;
@ -22,10 +22,13 @@ export type ParsedRealmJson = {
clientRoles: Record<string, string[]>;
}[];
roles: {
client: {
name: string;
containerId: string; // client id
}[];
client: Record<
string,
{
name: string;
containerId: string; // client id
}[]
>;
};
clients: {
id: string;
@ -41,6 +44,65 @@ export type ParsedRealmJson = {
}[];
};
const zParsedRealmJson = (() => {
type TargetType = ParsedRealmJson;
const zTargetType = z.object({
realm: z.string(),
loginTheme: z.string().optional(),
accountTheme: z.string().optional(),
adminTheme: z.string().optional(),
emailTheme: z.string().optional(),
eventsListeners: z.array(z.string()),
users: z.array(
z.object({
id: z.string(),
email: z.string(),
username: z.string(),
attributes: z.record(z.unknown()),
credentials: z.array(
z.object({
type: z.string()
})
),
clientRoles: z.record(z.array(z.string()))
})
),
roles: z.object({
client: z.record(
z.array(
z.object({
name: z.string(),
containerId: z.string()
})
)
)
}),
clients: z.array(
z.object({
id: z.string(),
clientId: z.string(),
baseUrl: z.string().optional(),
redirectUris: z.array(z.string()).optional(),
webOrigins: z.array(z.string()).optional(),
attributes: z
.object({
"post.logout.redirect.uris": z.string().optional()
})
.optional(),
protocol: z.string().optional(),
protocolMappers: z.array(z.unknown()).optional()
})
)
});
type InferredType = z.infer<typeof zTargetType>;
assert<Equals<TargetType, InferredType>>;
return id<z.ZodType<TargetType>>(zTargetType);
})();
export function readRealmJsonFile(params: {
realmJsonFilePath: string;
}): ParsedRealmJson {
@ -50,63 +112,6 @@ export function readRealmJsonFile(params: {
fs.readFileSync(realmJsonFilePath).toString("utf8")
) as unknown;
const zParsedRealmJson = (() => {
type TargetType = ParsedRealmJson;
const zTargetType = z.object({
name: z.string(),
loginTheme: z.string().optional(),
accountTheme: z.string().optional(),
adminTheme: z.string().optional(),
emailTheme: z.string().optional(),
eventsListeners: z.array(z.string()),
users: z.array(
z.object({
id: z.string(),
email: z.string(),
username: z.string(),
attributes: z.record(z.unknown()),
credentials: z.array(
z.object({
type: z.string()
})
),
clientRoles: z.record(z.array(z.string()))
})
),
roles: z.object({
client: z.array(
z.object({
name: z.string(),
containerId: z.string()
})
)
}),
clients: z.array(
z.object({
id: z.string(),
clientId: z.string(),
baseUrl: z.string().optional(),
redirectUris: z.array(z.string()).optional(),
webOrigins: z.array(z.string()).optional(),
attributes: z
.object({
"post.logout.redirect.uris": z.string().optional()
})
.optional(),
protocol: z.string().optional(),
protocolMappers: z.array(z.unknown()).optional()
})
)
});
type InferredType = z.infer<typeof zTargetType>;
assert<Equals<TargetType, InferredType>>;
return id<z.ZodType<TargetType>>(zTargetType);
})();
zParsedRealmJson.parse(parsedRealmJson);
assert(is<ParsedRealmJson>(parsedRealmJson));

View File

@ -51,7 +51,7 @@ export function prepareRealmConfig(params: {
}
return {
realmName: parsedRealmJson.name,
realmName: parsedRealmJson.realm,
clientName: clientId,
username
};
@ -138,7 +138,7 @@ function addOrEditTestUser(params: {
newUser.clientRoles = {};
for (const clientRole of parsedRealmJson.roles.client) {
for (const clientRole of Object.values(parsedRealmJson.roles.client).flat()) {
const clientName = nameByClientId[clientRole.containerId];
assert(clientName !== undefined);