/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { ValueSchema } from "../core";
import { RestrictiveReadonlyRecord } from "../util";
import { FieldKinds } from "./default-field-kinds";
import { SchemaLibraryData, SchemaLintConfiguration, AllowedTypes, TreeSchema, FieldSchema, TypedSchemaCollection, RecursiveTreeSchema, FlexList } from "./typed-schema";
import { FieldKind } from "./modular-schema";
/**
 * Builds schema libraries, and the schema within them.
 * @sealed @alpha
 */
export declare class SchemaBuilder {
    readonly name: string;
    private readonly lintConfiguration;
    private readonly libraries;
    private finalized;
    private readonly treeSchema;
    private readonly adapters;
    /**
     * @param name - Name used to refer to this builder in error messages. Has no impact on the actual generated schema.
     * @param lint - Optional configuration for "linting". See {@link SchemaLintConfiguration}. Currently defaults to enabling all lints.
     * @param libraries - Libraries to include in this one. See `addLibraries` for details.
     */
    constructor(name: string, lint?: Partial<SchemaLintConfiguration>, ...libraries: SchemaLibrary[]);
    /**
     * Adds more libraries to this one.
     *
     * Unlike adding of individual schema, adding of libraries is idempotent.
     * If a single library is added multiple times (even indirectly via libraries it was added into),
     * only a single copy will be included, so they will not conflict.
     * This allows adding any library this one depends on without risk of conflicts for users of this library.
     * Contents within the added libraries can still conflict however.
     * Such errors will be reported when finalizing this builder into a library of document schema.
     */
    addLibraries(...libraries: SchemaLibrary[]): void;
    private addNodeSchema;
    /**
     * Define (and add to this library) a {@link TreeSchema} for a {@link Struct} node.
     *
     * The name must be unique among all TreeSchema in the the document schema.
     */
    struct<Name extends string, T extends RestrictiveReadonlyRecord<string, FieldSchema>>(name: Name, t: T): TreeSchema<Name, {
        structFields: T;
    }>;
    /**
     * Same as `struct` but with less type safety and works for recursive objects.
     * Reduced type safety is a side effect of a workaround for a TypeScript limitation.
     *
     * See note on RecursiveTreeSchema for details.
     */
    structRecursive<Name extends string, T>(name: Name, t: T): TreeSchema<Name, {
        structFields: T;
    }>;
    /**
     * Define (and add to this library) a {@link TreeSchema} for a {@link MapNode}.
     */
    map<Name extends string, T extends FieldSchema>(name: Name, fieldSchema: T): TreeSchema<Name, {
        mapFields: T;
    }>;
    /**
     * Same as `map` but with less type safety and works for recursive objects.
     * Reduced type safety is a side effect of a workaround for a TypeScript limitation.
     *
     * See note on RecursiveTreeSchema for details.
     */
    mapRecursive<Name extends string, T>(name: Name, t: T): TreeSchema<Name, {
        mapFields: T;
    }>;
    /**
     * Define (and add to this library) a {@link TreeSchema} for a {@link FieldNode}.
     *
     * The name must be unique among all TreeSchema in the the document schema.
     *
     * @privateRemarks
     * TODO: Write and link document outlining field vs node data model and the separation of concerns related to that.
     * TODO: Maybe find a better name for this.
     */
    fieldNode<Name extends string, T extends FieldSchema>(name: Name, t: T): TreeSchema<Name, {
        structFields: {
            [""]: T;
        };
    }>;
    /**
     * Same as `fieldNode` but with less type safety and works for recursive objects.
     * Reduced type safety is a side effect of a workaround for a TypeScript limitation.
     *
     * See note on RecursiveTreeSchema for details.
     */
    fieldNodeRecursive<Name extends string, T>(name: Name, t: T): TreeSchema<Name, {
        structFields: {
            [""]: T;
        };
    }>;
    /**
     * Define (and add to this library) a {@link TreeSchema} for a node that wraps a value.
     * Such nodes will be implicitly unwrapped to the value in some APIs.
     *
     * The name must be unique among all TreeSchema in the the document schema.
     *
     * In addition to the normal properties of all nodes (having a schema for example),
     * Leaf nodes only contain a value.
     * Leaf nodes cannot have fields.
     *
     * TODO: Maybe ban undefined from allowed values here.
     * TODO: Decide and document how unwrapping works for non-primitive terminals.
     */
    leaf<Name extends string, T extends ValueSchema>(name: Name, t: T): TreeSchema<Name, {
        leafValue: T;
    }>;
    /**
     * Define a {@link FieldSchema}.
     *
     * @param kind - The [kind](https://en.wikipedia.org/wiki/Kind_(type_theory)) of this field.
     * Determine the multiplicity, viewing and editing APIs as well as the merge resolution policy.
     * @param allowedTypes - What types of children are allowed in this field.
     * @returns a {@link FieldSchema} which can be used as a struct field (see {@link SchemaBuilder.struct}),
     * a map field (see {@link SchemaBuilder.map}), a field node(see {@link SchemaBuilder.fieldNode}) or the root field (see {@link SchemaBuilder.intoDocumentSchema}).
     *
     * @privateRemarks
     * TODO: since this APi surface is using classes, maybe just have users do `new FieldSchema` instead?
     */
    static field<Kind extends FieldKind, T extends AllowedTypes>(kind: Kind, ...allowedTypes: T): FieldSchema<Kind, T>;
    /**
     * Define a schema for an {@link OptionalField}.
     * Shorthand or passing `FieldKinds.optional` to {@link SchemaBuilder.field}.
     */
    static fieldOptional<T extends AllowedTypes>(...allowedTypes: T): FieldSchema<typeof FieldKinds.optional, T>;
    /**
     * Define a schema for a {@link RequiredField}.
     * Shorthand or passing `FieldKinds.value` to {@link SchemaBuilder.field}.
     *
     * @privateRemarks
     * TODO: Consider adding even shorter syntax where:
     * - AllowedTypes can be used as a FieldSchema (Or SchemaBuilder takes a default field kind).
     * - A TreeSchema can be used as AllowedTypes in the non-polymorphic case.
     */
    static fieldValue<T extends AllowedTypes>(...allowedTypes: T): FieldSchema<typeof FieldKinds.value, T>;
    /**
     * Define a schema for a {@link Sequence} field.
     */
    static fieldSequence<T extends AllowedTypes>(...t: T): FieldSchema<typeof FieldKinds.sequence, T>;
    /**
     * Define a schema for a field.
     * Same as {@link SchemaBuilder.field} but is less type safe and supports recursive types.
     * This API is less safe to work around a limitation of TypeScript.
     *
     * T must extends `AllowedTypes`: This cannot be enforced via TypeScript since such an "extends" clauses cause recursive types to error with:
     * "'theSchema' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer."
     *
     * TODO: Try and find a way to provide a more specific type without triggering the above error.
     */
    static fieldRecursive<Kind extends FieldKind, T extends FlexList<RecursiveTreeSchema>>(kind: Kind, ...allowedTypes: T): FieldSchema<Kind, T>;
    private finalize;
    /**
     * Produce SchemaLibraries which capture the content added to this builder, as well as any additional SchemaLibraries that were added to it.
     * May only be called once after adding content to builder is complete.
     */
    intoLibrary(): SchemaLibrary;
    /**
     * Produce a TypedSchemaCollection which captures the content added to this builder, any additional SchemaLibraries that were added to it and a root field.
     * Can be used with schematize to provide schema aware access to document content.
     *
     * May only be called once after adding content to builder is complete.
     */
    intoDocumentSchema<Kind extends FieldKind, Types extends AllowedTypes>(root: FieldSchema<Kind, Types>): TypedSchemaCollection<FieldSchema<Kind, Types>>;
}
/**
 * Schema information collected by a SchemaBuilder, including referenced libraries.
 * Can be aggregated into other libraries by adding to their builders.
 * @alpha
 */
export interface SchemaLibrary extends TypedSchemaCollection {
    /**
     * Schema data aggregated from a collection of libraries by a SchemaBuilder.
     */
    readonly libraries: ReadonlySet<SchemaLibraryData>;
}
//# sourceMappingURL=schemaBuilder.d.ts.map