import type { ParseContext, SchemaNode } from "../types.js"; import { BaseSchema } from "./base.js"; import { ISSUE_CODES } from "../issue-codes.js"; import { describeType } from "../util.js"; export class RecordSchema< T extends BaseSchema = BaseSchema, > extends BaseSchema, Record> { private _valueSchema: T; constructor(valueSchema: T) { super(); this._valueSchema = valueSchema; } _validate(input: unknown, ctx: ParseContext): unknown { if (typeof input !== "object" || input === null || Array.isArray(input)) { ctx.issues.push({ code: ISSUE_CODES.INVALID_TYPE, message: `Expected record, received ${describeType(input)}`, path: [...ctx.path], expected: "record", received: describeType(input), }); return undefined; } const obj = input as Record; const result: Record = Object.create(null); for (const [key, value] of Object.entries(obj)) { ctx.path.push(key); Object.defineProperty(result, key, { value: this._valueSchema._runPipeline(value, ctx), writable: true, enumerable: true, configurable: true, }); ctx.path.pop(); } Object.setPrototypeOf(result, Object.prototype); return result; } _children(): BaseSchema[] { return [this._valueSchema]; } _toNode(): SchemaNode { const node = { kind: "record" as const, valueSchema: this._valueSchema._toNode(), }; this._addDefault(node as unknown as SchemaNode); return node as unknown as SchemaNode; } }