/** * The Producer schema DSL. * * A {@link Producer} describes how to turn one XML node into one typed value. It * is the single recursive unit of a schema: an object producer's fields are * themselves producers, an array producer's item is a producer, and so on all * the way down. {@link SchemaParser.produce} interprets this tree. * * Five kinds, each built by a combinator: * - `scalar` — a leaf: text (or an attribute) decoded into `T`. * - `object` — a fixed set of named fields, each a producer. * - `array` — a repeated subtree: `each` selects item nodes, `item` produces one. * - `oneOf` — an honest discriminated union (shared `base` + tagged `branches`). * - `custom` — the sole escape hatch, handed a narrow {@link NodeLens}. * * Absence model (see CONTEXT.md): a `required` field that is missing nulls its * *nearest enclosing object*; arrays *drop* null items (recording a warning); * only the document root throws. `required` is opt-in, so nothing cascades unless * a schema author asks for it. */ /** How a producer behaves when it finds no data. */ export type Presence = /** Missing → `null` (or `[]` for arrays). The default. */ "optional" /** Missing → the nearest enclosing object becomes `null` (root throws). */ | "required" /** Missing → the key is omitted entirely (needs `exactOptionalPropertyTypes`). */ | "omit"; /** * The narrow, relative-only surface a `CustomProducer` receives. * * A custom producer never sees the raw {@link XMLAdapter} or escapes its subtree — * it reads text and child nodes relative to the node it was mounted on. */ export interface NodeLens { /** Local (namespace-stripped) name of this lens' own node (`null` if none). */ name(): string | null; /** Trimmed text content of this lens' own node (`null` if empty). */ text(): string | null; /** Trimmed text at a relative XPath (`null` if the node is absent/empty). */ textAt(xpath: string): string | null; /** Value of an attribute reached by a relative XPath ending in `/@name`. */ attr(xpath: string): string | null; /** A lens per node matching a relative XPath. */ all(xpath: string): Array; } /** * Fields common to every producer kind. `presence` lives on each producer * interface instead (typed as the literal `P`), so its value can be recovered at * the type level. */ interface ProducerMeta { /** Relative XPath from the enclosing node to this producer's node. */ at?: string; /** Docstring carried into generated types as `/** *\/`. */ doc?: string; /** Group name carried into generated types as `@group`. */ group?: string; } /** * A producer carries two type params: its output type `T`, and its * {@link Presence} `P`. `P` is the literal type of the runtime `presence` field — * the same value drives both parsing and {@link ProducedFields} (which reads `P` * to decide whether a field's key is required or `omit` → optional). One field, * one source of truth; no phantom to keep in sync. */ export interface ScalarProducer extends ProducerMeta { kind: "scalar"; decode: (raw: string | null) => T; /** Absence behaviour (default `"optional"`). */ presence?: P; /** Phantom output type — never present at runtime. */ readonly _out?: T; } export interface ObjectProducer extends ProducerMeta { kind: "object"; fields: Record>; presence?: P; readonly _out?: T; } export interface ArrayProducer extends ProducerMeta { kind: "array"; /** Relative XPath selecting each item node. */ each: string; item: Producer; presence?: P; readonly _out?: T; } export interface CustomProducer extends ProducerMeta { kind: "custom"; produce: (lens: NodeLens) => T; presence?: P; readonly _out?: T; } /** One tagged branch of a {@link OneOfProducer}. */ export interface OneOfBranch { /** XPath whose existence selects this branch (first match wins). */ when: string; /** Relative XPath to the branch's node (defaults to the oneOf node). */ at?: string; /** Literal discriminant value written under the oneOf's `tagAs` key. */ tag: string; fields: Record>; } export interface OneOfProducer extends ProducerMeta { kind: "oneOf"; /** Field name that carries each branch's literal `tag`. */ tagAs: string; /** Fields parsed once and merged into every branch. */ base: Record>; branches: ReadonlyArray; presence?: P; readonly _out?: T; } export type Producer = ScalarProducer | ObjectProducer | ArrayProducer | CustomProducer | OneOfProducer; /** Flatten an intersection into a single object literal for legible hovers. */ type Simplify = { [K in keyof T]: T[K]; } & {}; /** Recover a producer's output type. Recurses in parallel with the runtime. */ export type Produced

= P extends { readonly _out?: infer T; } ? T : never; /** Recover a producer's {@link Presence} (absent → the `"optional"` default). */ type PresenceOf = X extends { presence?: infer P; } ? (P extends Presence ? P : "optional") : "optional"; type OmitPresenceKeys = { [K in keyof F]: PresenceOf extends "omit" ? K : never; }[keyof F]; /** * The output type of an object built from a fields map. A field whose producer * has `presence: "omit"` becomes an **optional** key (`key?:`); every other * field is a required key. Under `exactOptionalPropertyTypes` this exactly * mirrors the runtime absence model. */ export type ProducedFields = Simplify<{ [K in Exclude>]: Produced; } & { [K in OmitPresenceKeys]?: Produced; }>; /** Meta accepted by every combinator, minus `presence` (captured generically). */ interface BaseMeta { at?: string; doc?: string; group?: string; } type LeafOpts

= BaseMeta & { presence?: P; }; type ScalarOpts = LeafOpts

& { decode: (raw: string | null) => T; }; /** A leaf producer with an explicit decoder. */ export declare function scalar(opts: ScalarOpts): ScalarProducer; /** Raw trimmed text (`string | null`). */ export declare function text

(at?: string, opts?: LeafOpts

): ScalarProducer; /** Precision-preserving ISO date/dateTime string (`string | null`). */ export declare function date

(at?: string, opts?: LeafOpts

): ScalarProducer; /** Decimal number (`number | null`). */ export declare function number_

(at?: string, opts?: LeafOpts

): ScalarProducer; /** Integer (`number | null`). */ export declare function integer

(at?: string, opts?: LeafOpts

): ScalarProducer; /** Boolean (`boolean | null`), understanding BRO's `ja`/`nee`. */ export declare function boolean_

(at?: string, opts?: LeafOpts

): ScalarProducer; /** BRO quality class (`number | null`), understanding `"klasse2"` and `"2"`. */ export declare function qualityClass

(at?: string, opts?: LeafOpts

): ScalarProducer; /** A fixed set of named fields. Output type is inferred from `fields`. */ export declare function object_>, P extends Presence = "optional">(opts: { fields: F; presence?: P; } & BaseMeta): ObjectProducer, P>; /** A repeated subtree. `each` selects item nodes; `item` produces one value. */ export declare function array(opts: { each: string; item: Producer; presence?: P; } & BaseMeta): ArrayProducer, P>; /** The escape hatch: a decoder handed a relative-only {@link NodeLens}. */ export declare function custom(opts: { produce: (lens: NodeLens) => T; presence?: P; } & BaseMeta): CustomProducer; /** A branch as written at the `oneOf` call site (captured for type inference). */ interface BranchInput> = Record>> { when: string; at?: string; tag: Tag; fields: F; } /** Output type of one branch: shared base ∪ branch fields ∪ the tag literal. */ type BranchOut = B extends { tag: infer Tag extends string; fields: infer F; } ? Simplify & ProducedFields & Record> : never; /** The discriminated union over all branches (mapped tuple → indexed union). */ type OneOfOut> = { [I in keyof Branches]: BranchOut; }[number]; /** * An honest discriminated union. `base` fields are parsed once; the first branch * whose `when` XPath exists is parsed and merged, with its literal `tag` written * under `tagAs`. * * The output type is **inferred**: a discriminated union keyed on `tagAs`, each * member being the shared `base` fields plus that branch's `fields` plus the * literal `tag`. Presence is honoured throughout (`omit` → optional key). */ export declare function oneOf>, const Branches extends ReadonlyArray, P extends Presence = "optional">(opts: { tagAs: TagKey; base?: Base; branches: Branches; presence?: P; } & BaseMeta): OneOfProducer, P>; export {}; //# sourceMappingURL=producer.d.ts.map