121 lines
4.0 KiB
TypeScript
121 lines
4.0 KiB
TypeScript
import type { TSchema } from "@sinclair/typebox";
|
|
|
|
import { Type } from "@sinclair/typebox";
|
|
|
|
import { variableValueSchema } from "./fragments";
|
|
|
|
type SchemaKind = "authoring" | "normalized";
|
|
|
|
const LOG_LEVELS = ["trace", "debug", "info", "warn", "error", "fatal"] as const;
|
|
const ROTATION_FREQUENCIES = ["hourly", "daily", "weekly"] as const;
|
|
|
|
const sizeSchema = Type.Union([Type.String(), Type.Integer({ minimum: 0 })]);
|
|
|
|
export function createAuthoringConfigSchema(): TSchema {
|
|
return createConfigSchemaForKind("authoring");
|
|
}
|
|
|
|
export function createExternalConfigSchema(): Record<string, unknown> {
|
|
return {
|
|
...cloneSchema(createAuthoringConfigSchema()),
|
|
$id: "https://app.local/config.schema.json",
|
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
};
|
|
}
|
|
|
|
export function createNormalizedConfigSchema(): TSchema {
|
|
return createConfigSchemaForKind("normalized");
|
|
}
|
|
|
|
function cloneSchema(schema: TSchema): Record<string, unknown> {
|
|
return JSON.parse(JSON.stringify(schema)) as Record<string, unknown>;
|
|
}
|
|
|
|
function createAuthoringFieldSchema(schema: TSchema): TSchema {
|
|
return Type.Unsafe({ anyOf: [schema, { pattern: "^\\$\\{[^}]+\\}$", type: "string" }] });
|
|
}
|
|
|
|
function createConfigSchemaForKind(kind: SchemaKind): TSchema {
|
|
const properties: Record<string, TSchema> = {
|
|
server: Type.Optional(createServerSchema(kind)),
|
|
};
|
|
if (kind === "authoring") {
|
|
properties["variables"] = Type.Optional(
|
|
Type.Record(Type.String({ pattern: "^[a-zA-Z_][a-zA-Z0-9_]*$" }), variableValueSchema),
|
|
);
|
|
}
|
|
return Type.Object(properties, { additionalProperties: false });
|
|
}
|
|
|
|
function createLoggingSchema(kind: SchemaKind): TSchema {
|
|
const logLevelSchema = Type.Union(LOG_LEVELS.map((l) => Type.Literal(l)) as unknown as [TSchema, ...TSchema[]]);
|
|
const logLevel = kind === "authoring" ? createAuthoringFieldSchema(logLevelSchema) : logLevelSchema;
|
|
const frequency =
|
|
kind === "authoring"
|
|
? createAuthoringFieldSchema(
|
|
Type.Union(ROTATION_FREQUENCIES.map((f) => Type.Literal(f)) as unknown as [TSchema, ...TSchema[]]),
|
|
)
|
|
: Type.Union(ROTATION_FREQUENCIES.map((f) => Type.Literal(f)) as unknown as [TSchema, ...TSchema[]]);
|
|
const rotationSize = kind === "authoring" ? createAuthoringFieldSchema(sizeSchema) : sizeSchema;
|
|
const rotationMaxFiles =
|
|
kind === "authoring" ? createAuthoringFieldSchema(Type.Integer({ minimum: 1 })) : Type.Integer({ minimum: 1 });
|
|
|
|
return Type.Object(
|
|
{
|
|
console: Type.Optional(Type.Object({ level: Type.Optional(logLevel) }, { additionalProperties: false })),
|
|
file: Type.Optional(
|
|
Type.Object(
|
|
{
|
|
level: Type.Optional(logLevel),
|
|
path: Type.Optional(Type.String({ minLength: 1 })),
|
|
rotation: Type.Optional(
|
|
Type.Object(
|
|
{
|
|
frequency: Type.Optional(frequency),
|
|
maxFiles: Type.Optional(rotationMaxFiles),
|
|
size: Type.Optional(rotationSize),
|
|
},
|
|
{ additionalProperties: false },
|
|
),
|
|
),
|
|
},
|
|
{ additionalProperties: false },
|
|
),
|
|
),
|
|
level: Type.Optional(logLevel),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
}
|
|
|
|
function createServerSchema(kind: SchemaKind): TSchema {
|
|
return Type.Object(
|
|
{
|
|
listen: Type.Optional(
|
|
Type.Object(
|
|
{
|
|
host: Type.Optional(Type.String()),
|
|
port: Type.Optional(integerForKind(kind, { maximum: 65535, minimum: 0 })),
|
|
},
|
|
{ additionalProperties: false },
|
|
),
|
|
),
|
|
logging: Type.Optional(createLoggingSchema(kind)),
|
|
storage: Type.Optional(
|
|
Type.Object(
|
|
{
|
|
dataDir: Type.Optional(Type.String()),
|
|
},
|
|
{ additionalProperties: false },
|
|
),
|
|
),
|
|
},
|
|
{ additionalProperties: false },
|
|
);
|
|
}
|
|
|
|
function integerForKind(kind: SchemaKind, options?: Parameters<typeof Type.Integer>[0]): TSchema {
|
|
const schema = Type.Integer(options);
|
|
return kind === "authoring" ? createAuthoringFieldSchema(schema) : schema;
|
|
}
|