/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type ArrayNodeCustomizableSchema, type MapNodeCustomizableSchema, type ObjectNodeSchema, type RecordNodeCustomizableSchema } from "../node-kinds/index.js";
import { type NodeSchemaOptionsAlpha, type ObjectSchemaOptionsAlpha, type ScopedSchemaName } from "./schemaFactory.js";
import type { ImplicitFieldSchema } from "../fieldSchema.js";
import type { RestrictiveStringRecord } from "../../util/index.js";
import type { NodeKind, TreeNodeSchema, TreeNodeSchemaClass, ImplicitAllowedTypes, AnnotatedAllowedType, LazyItem, WithType, AllowedTypesMetadata, AllowedTypesFullFromMixed } from "../core/index.js";
import type { AllowedTypesFullFromMixedUnsafe, AnnotatedAllowedTypeUnsafe, ArrayNodeCustomizableSchemaUnsafe, MapNodeCustomizableSchemaUnsafe, System_Unsafe, TreeRecordNodeUnsafe, UnannotateAllowedTypeUnsafe, Unenforced } from "./typesUnsafe.js";
import type { SimpleObjectNodeSchema } from "../simpleSchema.js";
import { SchemaFactoryBeta } from "./schemaFactoryBeta.js";
import type { FieldProps, FieldSchemaAlpha, FieldPropsAlpha, FieldKind } from "../fieldSchema.js";
import type { LeafSchema } from "../leafNodeSchema.js";
import type { SimpleLeafNodeSchema } from "../simpleSchema.js";
import type { FieldSchemaAlphaUnsafe } from "./typesUnsafe.js";
/**
 * Stateless APIs exposed via {@link SchemaFactoryAlpha} as both instance properties and as statics.
 * @remarks
 * See {@link SchemaStatics} for why this is useful.
 * @system @sealed @alpha
 */
export interface SchemaStaticsAlpha {
    /**
     * Declares a staged type in a set of {@link AllowedTypes}.
     *
     * @remarks
     * Staged allowed types add support for loading documents which may contain that type at the declared location.
     * This allows for an incremental rollout of a schema change to add a {@link TreeNodeSchema} to an {@link AllowedTypes} without breaking cross version collaboration.
     * A guide on this process can be found here: https://fluidframework.com/docs/data-structures/tree/schema-evolution/allowed-types-rollout
     *
     * Once enough clients have the type staged (and thus can read documents which allow it), documents can start being created and upgraded to allow the staged type.
     * This is done by deploying a new version of the app which removes the `staged` wrapper around the allowed type in the the schema definition.
     * This will also require {@link TreeView.upgradeSchema|upgrading the schema} for existing documents.
     *
     * Using a staged allowed type in a schema is just like using the schema as an allowed type with the following exceptions:
     *
     * 1. {@link TreeView.initialize} will omit the staged allowed type from the newly created stored schema.
     * 2. {@link TreeView.upgradeSchema} will omit the staged allowed type from the the upgraded stored schema.
     * 3. When evaluating {@link TreeView.compatibility}, it will be viewable even if the staged allowed type is not present in the stored schema's corresponding allowed types.
     * 4. Because of the above, it is possible to get errors when inserting content which uses the staged allowed type into a tree whose stored schema does not permit it.
     *
     * Currently, `staged` is not supported in the recursive type APIs: this is a known limitation which future versions of the API will address.
     *
     * @example
     * A full code example of the schema migration process can be found in our {@link https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/src/test/simple-tree/api/stagedSchemaUpgrade.spec.ts | tests}.
     *
     * @privateRemarks
     * TODO:#44317 staged allowed types rely on schema validation of stored schema to output errors, these errors are not very
     * user friendly and should be improved, particularly in the case of staged allowed types
     *
     * TODO: AB#45711: Update the docs above when recursive type support is added.
     */
    readonly staged: <const T extends LazyItem<TreeNodeSchema>>(t: T | AnnotatedAllowedType<T>) => AnnotatedAllowedType<T>;
    /**
     * Normalize information about a set of {@link AllowedTypes} into an {@link AllowedTypesFull}.
     * @remarks
     * This can take in {@link AnnotatedAllowedType} to preserve their annotations.
     */
    readonly types: <const T extends readonly (AnnotatedAllowedType | LazyItem<TreeNodeSchema>)[]>(t: T, metadata?: AllowedTypesMetadata) => AllowedTypesFullFromMixed<T>;
    /**
     * {@link SchemaStaticsAlpha.staged} except tweaked to work better for recursive types.
     * Use with {@link ValidateRecursiveSchema} for improved type safety.
     * @remarks
     * This version of {@link SchemaStaticsAlpha.staged} has fewer type constraints to work around TypeScript limitations, see {@link Unenforced}.
     * See {@link ValidateRecursiveSchema} for additional information about using recursive schema.
     */
    stagedRecursive: <const T extends Unenforced<AnnotatedAllowedType | LazyItem<TreeNodeSchema>>>(t: T) => AnnotatedAllowedTypeUnsafe<UnannotateAllowedTypeUnsafe<T>>;
    /**
     * {@link SchemaStaticsAlpha.types} except tweaked to work better for recursive types.
     * Use with {@link ValidateRecursiveSchema} for improved type safety.
     * @remarks
     * This version of {@link SchemaStaticsAlpha.types} has fewer type constraints to work around TypeScript limitations, see {@link Unenforced}.
     * See {@link ValidateRecursiveSchema} for additional information about using recursive schema.
     * @privateRemarks
     * If all inputs (at least recursive ones) were required to be annotated, this could be typed more strongly.
     * In that case it could use `T extends readonly (AnnotatedAllowedTypeUnsafe | LazyItem<System_Unsafe.TreeNodeSchemaUnsafe>)[]`.
     */
    readonly typesRecursive: <const T extends readonly Unenforced<AnnotatedAllowedType | LazyItem<TreeNodeSchema>>[]>(t: T, metadata?: AllowedTypesMetadata) => AllowedTypesFullFromMixedUnsafe<T>;
}
/**
 * {@link SchemaFactory} with additional alpha APIs.
 *
 * @alpha
 * @privateRemarks
 * When building schema, when `options` is not provided, `TCustomMetadata` is inferred as `unknown`.
 * If desired, this could be made to infer `undefined` instead by adding overloads for everything,
 * but currently it is not worth the maintenance overhead as there is no use case which this is known to be helpful for.
 */
export declare class SchemaFactoryAlpha<out TScope extends string | undefined = string | undefined, TName extends number | string = string> extends SchemaFactoryBeta<TScope, TName> {
    /**
     * Define a {@link TreeNodeSchemaClass} for a {@link TreeObjectNode}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     * @param fields - Schema for fields of the object node's schema. Defines what children can be placed under each key.
     * @param options - Additional options for the schema.
     */
    objectAlpha<const Name extends TName, const T extends RestrictiveStringRecord<ImplicitFieldSchema>, const TCustomMetadata = unknown>(name: Name, fields: T, options?: ObjectSchemaOptionsAlpha<TCustomMetadata>): ObjectNodeSchema<ScopedSchemaName<TScope, Name>, T, true, TCustomMetadata> & {
        /**
         * Typing checking workaround: not for for actual use.
         * @remarks
         * This API collides with {@link TreeNodeSchemaCore.createFromInsertable} to disable a type checking optimization which produces different and undesired results.
         * See {@link https://github.com/microsoft/TypeScript/issues/59049#issuecomment-2773459693} for more details.
         * @privateRemarks
         * The specific issue here is non-empty POJO mode object schema not being assignable to `ObjectNodeSchema`,
         * See the above link and the tests in objectNode.spec.ts which reference it.
         * @system
         */
        readonly createFromInsertable: unknown;
    };
    /**
     * {@inheritdoc SchemaFactory.objectRecursive}
     */
    objectRecursive<const Name extends TName, const T extends RestrictiveStringRecord<System_Unsafe.ImplicitFieldSchemaUnsafe>, const TCustomMetadata = unknown>(name: Name, t: T, options?: ObjectSchemaOptionsAlpha<TCustomMetadata>): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, System_Unsafe.TreeObjectNodeUnsafe<T, ScopedSchemaName<TScope, Name>>, object & System_Unsafe.InsertableObjectFromSchemaRecordUnsafe<T>, false, T, never, TCustomMetadata> & SimpleObjectNodeSchema<TCustomMetadata> & Pick<ObjectNodeSchema, "fields">;
    /**
     * {@inheritDoc SchemaStatics.leaves}
     */
    static readonly leaves: readonly [LeafSchema<"string", string> & SimpleLeafNodeSchema, LeafSchema<"number", number> & SimpleLeafNodeSchema, LeafSchema<"boolean", boolean> & SimpleLeafNodeSchema, LeafSchema<"null", null> & SimpleLeafNodeSchema, LeafSchema<"handle", import("@fluidframework/core-interfaces").IFluidHandle<unknown>> & SimpleLeafNodeSchema];
    /**
     * {@inheritDoc SchemaStatics.optional}
     */
    static readonly optional: <const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlpha<FieldKind.Optional, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.required}
     */
    static readonly required: <const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlpha<FieldKind.Required, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.optionalRecursive}
     */
    static readonly optionalRecursive: <const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlphaUnsafe<FieldKind.Optional, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.requiredRecursive}
     */
    static readonly requiredRecursive: <const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlphaUnsafe<FieldKind.Required, T, TCustomMetadata>;
    /**
     * Like {@link SchemaFactory.identifier} but static and a factory function that can be provided {@link FieldProps}.
     */
    static readonly identifier: <const TCustomMetadata = unknown>(props?: Omit<FieldProps<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlpha<FieldKind.Identifier, LeafSchema<"string", string> & SimpleLeafNodeSchema, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.leaves}
     */
    readonly leaves: readonly [LeafSchema<"string", string> & SimpleLeafNodeSchema, LeafSchema<"number", number> & SimpleLeafNodeSchema, LeafSchema<"boolean", boolean> & SimpleLeafNodeSchema, LeafSchema<"null", null> & SimpleLeafNodeSchema, LeafSchema<"handle", import("@fluidframework/core-interfaces").IFluidHandle<unknown>> & SimpleLeafNodeSchema];
    /**
     * {@inheritDoc SchemaStatics.optional}
     */
    readonly optional: <const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlpha<FieldKind.Optional, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.required}
     */
    readonly required: <const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlpha<FieldKind.Required, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.optionalRecursive}
     */
    readonly optionalRecursive: <const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlphaUnsafe<FieldKind.Optional, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStatics.requiredRecursive}
     */
    readonly requiredRecursive: <const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldPropsAlpha<TCustomMetadata>, "defaultProvider"> | undefined) => FieldSchemaAlphaUnsafe<FieldKind.Required, T, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.staged}
     */
    static staged: <const T extends LazyItem<TreeNodeSchema>>(t: T | AnnotatedAllowedType<T>) => AnnotatedAllowedType<T>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.staged}
     */
    staged: <const T extends LazyItem<TreeNodeSchema>>(t: T | AnnotatedAllowedType<T>) => AnnotatedAllowedType<T>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.stagedRecursive}
     */
    static stagedRecursive: <const T extends unknown>(t: T) => AnnotatedAllowedTypeUnsafe<UnannotateAllowedTypeUnsafe<T>>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.stagedRecursive}
     */
    stagedRecursive: <const T extends unknown>(t: T) => AnnotatedAllowedTypeUnsafe<UnannotateAllowedTypeUnsafe<T>>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.types}
     */
    static types: <const T extends readonly (LazyItem<TreeNodeSchema> | AnnotatedAllowedType<LazyItem<TreeNodeSchema>>)[]>(t: T, metadata?: AllowedTypesMetadata | undefined) => AllowedTypesFullFromMixed<T>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.types}
     */
    types: <const T extends readonly (LazyItem<TreeNodeSchema> | AnnotatedAllowedType<LazyItem<TreeNodeSchema>>)[]>(t: T, metadata?: AllowedTypesMetadata | undefined) => AllowedTypesFullFromMixed<T>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.typesRecursive}
     */
    static typesRecursive: <const T extends readonly unknown[]>(t: T, metadata?: AllowedTypesMetadata | undefined) => AllowedTypesFullFromMixedUnsafe<T>;
    /**
     * {@inheritDoc SchemaStaticsAlpha.typesRecursive}
     */
    typesRecursive: <const T extends readonly unknown[]>(t: T, metadata?: AllowedTypesMetadata | undefined) => AllowedTypesFullFromMixedUnsafe<T>;
    /**
     * Define a {@link TreeNodeSchema} for a {@link TreeMapNode}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     * @param allowedTypes - The types that may appear as values in the map.
     * @param options - Additional options for the schema.
     *
     * @example
     * ```typescript
     * class NamedMap extends factory.map("name", factory.number, {
     * 	metadata: { description: "A map of numbers" }
     * }) {}
     * ```
     */
    mapAlpha<Name extends TName, const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>): MapNodeCustomizableSchema<ScopedSchemaName<TScope, Name>, T, true, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaFactory.objectRecursive}
     */
    mapRecursive<Name extends TName, const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>): MapNodeCustomizableSchemaUnsafe<ScopedSchemaName<TScope, Name>, T, TCustomMetadata>;
    /**
     * Define a {@link TreeNodeSchemaClass} for a {@link (TreeArrayNode:interface)}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     * @param allowedTypes - The types that may appear in the array.
     * @param options - Additional options for the schema.
     *
     * @example
     * ```typescript
     * class NamedArray extends factory.arrayAlpha("name", factory.number) {}
     * ```
     */
    arrayAlpha<const Name extends TName, const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>): ArrayNodeCustomizableSchema<ScopedSchemaName<TScope, Name>, T, true, TCustomMetadata>;
    /**
     * {@link SchemaFactory.arrayRecursive} but with support for some alpha features.
     */
    arrayRecursive<const Name extends TName, const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>): ArrayNodeCustomizableSchemaUnsafe<ScopedSchemaName<TScope, Name>, T, TCustomMetadata>;
    /**
     * Define (and add to this library) a {@link TreeNodeSchemaClass} for a {@link (TreeRecordNode:interface)}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     * @param allowedTypes - The types that may appear in the record.
     * @param options - Additional options for the schema.
     *
     * @example
     * ```typescript
     * class NamedRecord extends factory.recordAlpha("name", factory.number) {}
     * ```
     */
    recordAlpha<const Name extends TName, const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>): RecordNodeCustomizableSchema<ScopedSchemaName<TScope, Name>, T, true, TCustomMetadata>;
    /**
     * {@link SchemaFactoryBeta.(record:2)} except tweaked to work better for recursive types.
     * Use with {@link ValidateRecursiveSchema} for improved type safety.
     * @remarks
     * This version of `SchemaFactory.record` uses the same workarounds as {@link SchemaFactory.objectRecursive}.
     * See {@link ValidateRecursiveSchema} for additional information about using recursive schema.
     */
    recordRecursive<Name extends TName, const T extends System_Unsafe.ImplicitAllowedTypesUnsafe, const TCustomMetadata = unknown>(name: Name, allowedTypes: T, options?: NodeSchemaOptionsAlpha<TCustomMetadata>): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Record, TreeRecordNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Record, unknown>, {
        readonly [x: string]: System_Unsafe.InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>;
    }, false, T, undefined, TCustomMetadata>;
    /**
     * {@inheritDoc SchemaFactoryBeta.scopedFactory}
     */
    scopedFactoryAlpha<const T extends TName, TNameInner extends number | string = string>(name: T): SchemaFactoryAlpha<ScopedSchemaName<TScope, T>, TNameInner>;
}
//# sourceMappingURL=schemaFactoryAlpha.d.ts.map