import { FluidObject } from '@fluidframework/core-interfaces';
import { IChannel } from '@fluidframework/datastore-definitions';
import { IChannelAttributes } from '@fluidframework/datastore-definitions';
import { IChannelFactory } from '@fluidframework/datastore-definitions';
import { IChannelServices } from '@fluidframework/datastore-definitions';
import { IFluidDataStoreRuntime } from '@fluidframework/datastore-definitions';
import { IFluidHandle } from '@fluidframework/core-interfaces';
import { IFluidLoadable } from '@fluidframework/core-interfaces';
import { ISharedObject } from '@fluidframework/shared-object-base';
import { ISharedObjectKind } from '@fluidframework/shared-object-base';
import { SessionSpaceCompressedId } from '@fluidframework/id-compressor';
import { StableId } from '@fluidframework/id-compressor';
import type { Static } from '@sinclair/typebox';
import type { TSchema } from '@sinclair/typebox';

/* Excluded from this release type: adaptEnum */

/* Excluded from this release type: Adapters */

/**
 * Types for use in fields.
 * @public
 */
export declare type AllowedTypes = readonly LazyItem<TreeNodeSchema>[];

/* Excluded from this release type: AllowedTypeSet */

/* Excluded from this release type: AllowedTypesToFlexInsertableTree */

/* Excluded from this release type: AllowedUpdateType */

/* Excluded from this release type: AllowOptional */

/* Excluded from this release type: AllowOptionalNotFlattened */

/* Excluded from this release type: Anchor */

/* Excluded from this release type: AnchorEvents */

/* Excluded from this release type: AnchorLocator */

/* Excluded from this release type: AnchorNode */

/* Excluded from this release type: AnchorSet */

/* Excluded from this release type: AnchorSetRootEvents */

/* Excluded from this release type: AnchorSlot */

/* Excluded from this release type: anchorSlot */

/* Excluded from this release type: AnnouncedVisitor */

/* Excluded from this release type: Any */

/**
 * Suitable for output.
 * For input must error on side of excluding undefined instead.
 * @public
 */
export declare type ApplyKind<T, Kind extends FieldKind> = Kind extends FieldKind.Required ? T : undefined | T;

/* Excluded from this release type: ApplyMultiplicity */

/* Excluded from this release type: arrayLikeMarkerSymbol */

/* Excluded from this release type: ArrayLikeMut */

/* Excluded from this release type: AssignableFieldKinds */

/* Excluded from this release type: Assume */

/* Excluded from this release type: Brand */

/* Excluded from this release type: brand */

/* Excluded from this release type: BrandedKey */

/* Excluded from this release type: BrandedKeyContent */

/* Excluded from this release type: BrandedMapSubset */

/* Excluded from this release type: BrandedType */

/* Excluded from this release type: buildTreeConfiguration */

/* Excluded from this release type: ChangesetLocalId */

/* Excluded from this release type: CheckoutEvents */

/* Excluded from this release type: CheckTypesOverlap */

/* Excluded from this release type: ChildCollection */

/* Excluded from this release type: ChildLocation */

/* Excluded from this release type: CollectOptions */

/**
 * The type of a commit. This is used to describe the context in which the commit was created.
 *
 * @public
 */
export declare enum CommitKind {
    /** A commit corresponding to a change that is not the result of an undo/redo. */
    Default = 0,
    /** A commit that is the result of an undo. */
    Undo = 1,
    /** A commit that is the result of a redo. */
    Redo = 2
}

/**
 * Information about a commit that has been applied.
 *
 * @public
 */
export declare interface CommitMetadata {
    /**
     * A {@link CommitKind} enum value describing whether the commit represents an Edit, an Undo, or a Redo.
     */
    readonly kind: CommitKind;
    /**
     * Indicates whether the commit is a local edit
     */
    readonly isLocal: boolean;
}

/* Excluded from this release type: compareLocalNodeKeys */

/* Excluded from this release type: configuredSharedTree */

/* Excluded from this release type: ContextuallyTypedFieldData */

/* Excluded from this release type: ContextuallyTypedNodeData */

/* Excluded from this release type: ContextuallyTypedNodeDataObject */

/* Excluded from this release type: Contravariant */

/* Excluded from this release type: Covariant */

/* Excluded from this release type: createEmitter */

/* Excluded from this release type: CursorAdapter */

/* Excluded from this release type: cursorForJsonableTreeNode */

/* Excluded from this release type: cursorForTypedTreeData */

/* Excluded from this release type: cursorFromContextualData */

/* Excluded from this release type: CursorLocationType */

/* Excluded from this release type: CursorMarker */

/* Excluded from this release type: CursorWithNode */

/* Excluded from this release type: defaultSchemaPolicy */

/* Excluded from this release type: DeltaDetachedNodeBuild */

/* Excluded from this release type: DeltaDetachedNodeChanges */

/* Excluded from this release type: DeltaDetachedNodeDestruction */

/* Excluded from this release type: DeltaDetachedNodeId */

/* Excluded from this release type: DeltaDetachedNodeRename */

/* Excluded from this release type: DeltaFieldChanges */

/* Excluded from this release type: DeltaFieldMap */

/* Excluded from this release type: DeltaMark */

/* Excluded from this release type: DeltaProtoNode */

/* Excluded from this release type: DeltaRoot */

/* Excluded from this release type: DeltaVisitor */

/* Excluded from this release type: DetachedField */

/* Excluded from this release type: DetachedPlaceUpPath */

/* Excluded from this release type: DetachedRangeUpPath */

/**
 * Placeholder for `Symbol.dispose`.
 *
 * Replace this with `Symbol.dispose` when it is available.
 * @public
 */
export declare const disposeSymbol: unique symbol;

/* Excluded from this release type: EmptyKey */

/* Excluded from this release type: EmptyObject */

/* Excluded from this release type: encodeTreeSchema */

/* Excluded from this release type: enumFromStrings */

/* Excluded from this release type: Erased */

/* Excluded from this release type: ErasedTreeNodeSchemaDataFormat */

/* Excluded from this release type: ErasedType */

/**
 * Used to specify the kinds of events emitted by an {@link ISubscribable}.
 *
 * @remarks
 *
 * Any object type is a valid {@link Events}, but only the event-like properties of that
 * type will be included.
 *
 * @example
 *
 * ```typescript
 * interface MyEvents {
 *   load: (user: string, data: IUserData) => void;
 *   error: (errorCode: number) => void;
 * }
 * ```
 *
 * @public
 */
export declare type Events<E> = {
    [P in (string | symbol) & keyof E as IsEvent<E[P]> extends true ? P : never]: E[P];
};

/* Excluded from this release type: ExtractFromOpaque */

/* Excluded from this release type: extractFromOpaque */

/**
 * Get the `Item` type from a `LazyItem<Item>`.
 * @public
 */
export declare type ExtractItemType<Item extends LazyItem> = Item extends () => infer Result ? Result : Item;

/* Excluded from this release type: fail */

/* Excluded from this release type: FieldAnchor */

/* Excluded from this release type: FieldGenerator */

/* Excluded from this release type: FieldKey */

/**
 * Kind of a field on a node.
 * @public
 */
export declare enum FieldKind {
    /**
     * A field which can be empty or filled.
     * @remarks
     * Allows 0 or one child.
     */
    Optional = 0,
    /**
     * A field which must always be filled.
     * @remarks
     * Only allows exactly one child.
     */
    Required = 1
}

/* Excluded from this release type: FieldKindData */

/* Excluded from this release type: FieldKindIdentifier */

/* Excluded from this release type: FieldKinds */

/* Excluded from this release type: FieldLocation */

/* Excluded from this release type: FieldMapObject */

/**
 * Additional information to provide to a {@link FieldSchema}.
 *
 * @public
 */
export declare interface FieldProps {
    /**
     * The unique identifier of a field, used in the persisted form of the tree.
     *
     * @remarks
     * If not explicitly set via the schema, this is the same as the schema's property key.
     *
     * Specifying a stored key that differs from the property key is particularly useful in refactoring scenarios.
     * To update the developer-facing API, while maintaining backwards compatibility with existing SharedTree data,
     * you can change the property key and specify the previous property key as the stored key.
     *
     * Notes:
     *
     * - Stored keys have no impact on standard JavaScript behavior, on tree nodes. For example, `Object.keys`
     * will always return the property keys specified in the schema, ignoring any stored keys that differ from
     * the property keys.
     *
     * - When specifying stored keys in an object schema, you must ensure that the final set of stored keys
     * (accounting for those implicitly derived from property keys) contains no duplicates.
     * This is validated at runtime.
     *
     * @example Refactoring code without breaking compatibility with existing data
     *
     * Consider some existing object schema:
     *
     * ```TypeScript
     * class Point extends schemaFactory.object("Point", {
     * 	xPosition: schemaFactory.number,
     * 	yPosition: schemaFactory.number,
     * 	zPosition: schemaFactory.optional(schemaFactory.number),
     * });
     * ```
     *
     * Developers using nodes of this type would access the the `xPosition` property as `point.xPosition`.
     *
     * We would like to refactor the schema to omit "Position" from the property keys, but application data has
     * already been persisted using the original property keys. To maintain compatibility with existing data,
     * we can refactor the schema as follows:
     *
     * ```TypeScript
     * class Point extends schemaFactory.object("Point", {
     * 	x: schemaFactory.required(schemaFactory.number, { key: "xPosition" }),
     * 	y: schemaFactory.required(schemaFactory.number, { key: "yPosition" }),
     * 	z: schemaFactory.optional(schemaFactory.number, { key: "zPosition" }),
     * });
     * ```
     *
     * Now, developers can access the `x` property as `point.x`, while existing data can still be collaborated on.
     *
     * @defaultValue If not specified, the key that is persisted is the property key that was specified in the schema.
     */
    readonly key?: string;
}

/**
 * All policy for a specific field,
 * including functionality that does not have to be kept consistent across versions or deterministic.
 *
 * This can include policy for how to use this schema for "view" purposes, and well as how to expose editing APIs.
 * @sealed @public
 */
export declare class FieldSchema<out Kind extends FieldKind = FieldKind, out Types extends ImplicitAllowedTypes = ImplicitAllowedTypes> {
    /**
     * The {@link https://en.wikipedia.org/wiki/Kind_(type_theory) | kind } of this field.
     * Determines the multiplicity, viewing and editing APIs as well as the merge resolution policy.
     */
    readonly kind: Kind;
    /**
     * What types of tree nodes are allowed in this field.
     */
    readonly allowedTypes: Types;
    /**
     * Optional properties associated with the field.
     */
    readonly props?: FieldProps | undefined;
    /**
     * This class is used with instanceof, and therefore should have nominal typing.
     * This field enforces that.
     */
    protected _typeCheck?: MakeNominal;
    private readonly lazyTypes;
    /**
     * What types of tree nodes are allowed in this field.
     * @remarks Counterpart to {@link FieldSchema.allowedTypes}, with any lazy definitions evaluated.
     */
    get allowedTypeSet(): ReadonlySet<TreeNodeSchema>;
    constructor(
    /**
     * The {@link https://en.wikipedia.org/wiki/Kind_(type_theory) | kind } of this field.
     * Determines the multiplicity, viewing and editing APIs as well as the merge resolution policy.
     */
    kind: Kind, 
    /**
     * What types of tree nodes are allowed in this field.
     */
    allowedTypes: Types, 
    /**
     * Optional properties associated with the field.
     */
    props?: FieldProps | undefined);
}

/* Excluded from this release type: FieldSchemaUnsafe */

/* Excluded from this release type: FieldUpPath */

/* Excluded from this release type: FlattenKeys */

/* Excluded from this release type: FlexAllowedTypes */

/* Excluded from this release type: FlexFieldKind */

/* Excluded from this release type: FlexFieldNodeSchema */

/* Excluded from this release type: FlexFieldSchema */

/* Excluded from this release type: FlexibleFieldContent */

/* Excluded from this release type: FlexibleNodeContent */

/* Excluded from this release type: FlexibleNodeSubSequence */

/* Excluded from this release type: FlexImplicitAllowedTypes */

/* Excluded from this release type: FlexImplicitFieldSchema */

/**
 * A flexible way to list values.
 * Each item in the list can either be an "eager" **value** or a "lazy" **function that returns a value** (the latter allows cyclic references to work).
 * @privateRemarks
 * By default, items that are of type `"function"` will be considered lazy and all other items will be considered eager.
 * To force a `"function"` item to be treated as an eager item, call `markEager` before putting it in the list.
 * This is necessary e.g. when the eager list items are function types and the lazy items are functions that _return_ function types.
 * `FlexList`s are processed by `normalizeFlexList` and `normalizeFlexListEager`.
 * @public
 */
export declare type FlexList<Item = unknown> = readonly LazyItem<Item>[];

/**
 * Normalize FlexList type to a union.
 * @public
 */
export declare type FlexListToUnion<TList extends FlexList> = ExtractItemType<TList[number]>;

/* Excluded from this release type: FlexMapFieldSchema */

/* Excluded from this release type: FlexMapNodeSchema */

/* Excluded from this release type: FlexObjectNodeFields */

/* Excluded from this release type: FlexObjectNodeSchema */

/* Excluded from this release type: FlexTreeContext */

/* Excluded from this release type: FlexTreeEntity */

/* Excluded from this release type: FlexTreeEntityKind */

/* Excluded from this release type: FlexTreeField */

/* Excluded from this release type: FlexTreeFieldNode */

/* Excluded from this release type: FlexTreeLeafNode */

/* Excluded from this release type: FlexTreeMapNode */

/* Excluded from this release type: flexTreeMarker */

/* Excluded from this release type: FlexTreeNode */

/* Excluded from this release type: FlexTreeNodeEvents */

/* Excluded from this release type: FlexTreeNodeKeyField */

/* Excluded from this release type: FlexTreeNodeSchema */

/* Excluded from this release type: FlexTreeObjectNode */

/* Excluded from this release type: FlexTreeObjectNodeFields */

/* Excluded from this release type: FlexTreeObjectNodeFieldsInner */

/* Excluded from this release type: FlexTreeObjectNodeTyped */

/* Excluded from this release type: FlexTreeOptionalField */

/* Excluded from this release type: FlexTreeRequiredField */

/* Excluded from this release type: FlexTreeSchema */

/* Excluded from this release type: FlexTreeSequenceField */

/* Excluded from this release type: FlexTreeTypedField */

/* Excluded from this release type: FlexTreeTypedFieldInner */

/* Excluded from this release type: FlexTreeTypedNode */

/* Excluded from this release type: FlexTreeTypedNodeUnion */

/* Excluded from this release type: FlexTreeUnboxField */

/* Excluded from this release type: FlexTreeUnboxFieldInner */

/* Excluded from this release type: FlexTreeUnboxNode */

/* Excluded from this release type: FlexTreeUnboxNodeUnion */

/* Excluded from this release type: FlexTreeUnknownUnboxed */

/* Excluded from this release type: FlexTreeView */

/* Excluded from this release type: Forbidden */

/* Excluded from this release type: forbiddenFieldKindIdentifier */

/* Excluded from this release type: ForestEvents */

/* Excluded from this release type: ForestLocation */

/* Excluded from this release type: ForestType */

/* Excluded from this release type: FullSchemaPolicy */

/* Excluded from this release type: GenericFieldsNode */

/* Excluded from this release type: GenericTreeNode */

/* Excluded from this release type: HasListeners */

/* Excluded from this release type: ICodecOptions */

/* Excluded from this release type: IdAllocator */

/* Excluded from this release type: IDefaultEditBuilder */

/**
 * An object with an explicit lifetime that can be ended.
 * @privateRemarks
 * TODO: align this with core-utils/IDisposable and {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management| TypeScript's Disposable}.
 * @public
 */
export declare interface IDisposable {
    /**
     * Call to end the lifetime of this object.
     *
     * It is invalid to use this object after this,
     * except for operations which explicitly document they are valid after disposal.
     *
     * @remarks
     * May cleanup resources retained by this object.
     * Often includes un-registering from events and thus preventing other objects from retaining a reference to this indefinably.
     *
     * Usually the only operations allowed after disposal are querying if an object is already disposed,
     * but this can vary between implementations.
     */
    [disposeSymbol](): void;
}

/* Excluded from this release type: IEditableForest */

/* Excluded from this release type: IEmitter */

/* Excluded from this release type: IForestSubscription */

/**
 * Types allowed in a field.
 * @remarks
 * Implicitly treats a single type as an array of one type.
 * @public
 */
export declare type ImplicitAllowedTypes = AllowedTypes | TreeNodeSchema;

/**
 * Schema for a field of a tree node.
 * @remarks
 * Implicitly treats {@link ImplicitAllowedTypes} as a Required field of that type.
 * @public
 */
export declare type ImplicitFieldSchema = FieldSchema | ImplicitAllowedTypes;

/* Excluded from this release type: InitializeAndSchematizeConfiguration */

/* Excluded from this release type: _InlineTrick */

/* Excluded from this release type: InsertableFlexField */

/* Excluded from this release type: InsertableFlexNode */

/**
 * Helper used to produce types for:
 *
 * 1. Insertable content which can be used to construct an object node.
 *
 * 2. Insertable content which is an unhydrated object node.
 *
 * 3. Union of 1 and 2.
 *
 * @privateRemarks TODO: consider separating these cases into different types.
 *
 * @public
 */
export declare type InsertableObjectFromSchemaRecord<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>> = {
    readonly [Property in keyof T]: InsertableTreeFieldFromImplicitField<T[Property]>;
};

/* Excluded from this release type: InsertableObjectFromSchemaRecordUnsafe */

/**
 * Type of content that can be inserted into the tree for a field of the given schema.
 * @public
 */
export declare type InsertableTreeFieldFromImplicitField<TSchema extends ImplicitFieldSchema = FieldSchema> = TSchema extends FieldSchema<infer Kind, infer Types> ? ApplyKind<InsertableTreeNodeFromImplicitAllowedTypes<Types>, Kind> : TSchema extends ImplicitAllowedTypes ? InsertableTreeNodeFromImplicitAllowedTypes<TSchema> : unknown;

/* Excluded from this release type: InsertableTreeFieldFromImplicitFieldUnsafe */

/**
 * Type of content that can be inserted into the tree for a node of the given schema.
 * @public
 */
export declare type InsertableTreeNodeFromImplicitAllowedTypes<TSchema extends ImplicitAllowedTypes = TreeNodeSchema> = TSchema extends TreeNodeSchema ? InsertableTypedNode<TSchema> : TSchema extends AllowedTypes ? InsertableTypedNode<FlexListToUnion<TSchema>> : never;

/* Excluded from this release type: InsertableTreeNodeFromImplicitAllowedTypesUnsafe */

/**
 * Data which can be used as a node to be inserted.
 * Either an unhydrated node, or content to build a new node.
 * @public
 */
export declare type InsertableTypedNode<T extends TreeNodeSchema> = (T extends {
    implicitlyConstructable: true;
} ? NodeBuilderData<T> : never) | Unhydrated<NodeFromSchema<T>>;

/* Excluded from this release type: InsertableTypedNodeUnsafe */

/* Excluded from this release type: Invariant */

/* Excluded from this release type: isAny */

/* Excluded from this release type: IsArrayOfOne */

/* Excluded from this release type: ISchemaEditor */

/* Excluded from this release type: isContextuallyTypedNodeDataObject */

/**
 * `true` iff the given type is an acceptable shape for an event
 * @public
 */
export declare type IsEvent<Event> = Event extends (...args: any[]) => any ? true : false;

/* Excluded from this release type: ISharedTree */

/* Excluded from this release type: ISharedTreeEditor */

/* Excluded from this release type: isNeverField */

/**
 * An object which allows the registration of listeners so that subscribers can be notified when an event happens.
 *
 * `EventEmitter` can be used as a base class to implement this via extension.
 * @param E - All the events that this emitter supports
 * @example
 * ```ts
 * type MyEventEmitter = IEventEmitter<{
 *   load: (user: string, data: IUserData) => void;
 *   error: (errorCode: number) => void;
 * }>
 * ```
 * @privateRemarks
 * {@link createEmitter} can help implement this interface via delegation.
 *
 * @public
 */
export declare interface ISubscribable<E extends Events<E>> {
    /**
     * Register an event listener.
     * @param eventName - the name of the event
     * @param listener - the handler to run when the event is fired by the emitter
     * @returns a function which will deregister the listener when run. This function has undefined behavior
     * if called more than once.
     */
    on<K extends keyof Events<E>>(eventName: K, listener: E[K]): () => void;
}

/**
 * Used to insert iterable content into a {@link (TreeArrayNode:interface)}.
 * Use {@link (TreeArrayNode:variable).spread} to create an instance of this type.
 * @public
 */
export declare class IterableTreeArrayContent<T> implements Iterable<T> {
    private readonly content;
    private constructor();
    /**
     * Iterates over content for nodes to insert.
     */
    [Symbol.iterator](): Iterator<T>;
}

/* Excluded from this release type: ITransaction */

/**
 * Channel for a Fluid Tree DDS.
 * @remarks
 * Allows storing and collaboratively editing schema-aware hierarchial data.
 * @public
 */
export declare interface ITree extends IChannel {
    /**
     * Returns a {@link TreeView} using the provided schema.
     * If the tree's stored schema is compatible, this will provide a schema-aware API for accessing the tree's content.
     * If the provided schema is incompatible with the stored data, the view will instead expose an error indicating the incompatibility.
     *
     * @remarks
     * If the tree is uninitialized (has no schema and no content), the tree is initialized with the `initialTree` and
     * view `schema` in the provided `config`.
     *
     * The tree (now known to have been initialized) has its stored schema checked against the provided view schema.
     *
     * If the schemas are compatible, the returned {@link TreeView} will expose the root with a schema-aware API based on the provided view schema.
     *
     * If the schemas are not compatible, the view will indicate the error.
     *
     * Note that other clients can modify the document at any time, causing the view to enter or leave this error state: see {@link TreeView.events} for how to handle invalidation in these cases.
     *
     * Only one schematized view may exist for a given ITree at a time.
     * If creating a second, the first must be disposed before calling `schematize` again.
     *
     * @privateRemarks
     * TODO: Provide a way to make a generic view schema for any document.
     * TODO: Support adapters for handling out-of-schema data.
     *
     * Doing initialization here allows a small API that is hard to use incorrectly.
     * Other approaches tend to have easy-to-make mistakes.
     * For example, having a separate initialization function means apps can forget to call it, making an app that can only open existing documents,
     * or call it unconditionally leaving an app that can only create new documents.
     * It also would require the schema to be passed into separate places and could cause issues if they didn't match.
     * Since the initialization function couldn't return a typed tree, the type checking wouldn't help catch that.
     * Also, if an app manages to create a document, but the initialization fails to get persisted, an app that only calls the initialization function
     * on the create code-path (for example how a schematized factory might do it),
     * would leave the document in an unusable state which could not be repaired when it is reopened (by the same or other clients).
     * Additionally, once out of schema content adapters are properly supported (with lazy document updates),
     * this initialization could become just another out of schema content adapter and this initialization is no longer a special case.
     */
    schematize<TRoot extends ImplicitFieldSchema>(config: TreeConfiguration<TRoot>): TreeView<TreeFieldFromImplicitField<TRoot>>;
}

/* Excluded from this release type: ITreeCheckout */

/* Excluded from this release type: ITreeCheckoutFork */

/* Excluded from this release type: ITreeCursor */

/* Excluded from this release type: ITreeCursorSynchronous */

/* Excluded from this release type: ITreeSubscriptionCursor */

/* Excluded from this release type: ITreeSubscriptionCursorState */

/* Excluded from this release type: ITreeViewFork */

/* Excluded from this release type: JsonableTree */

/* Excluded from this release type: jsonableTreeFromCursor */

/* Excluded from this release type: JsonCompatible */

/* Excluded from this release type: JsonCompatibleObject */

/* Excluded from this release type: JsonCompatibleReadOnly */

/* Excluded from this release type: JsonValidator */

/**
 * An "eager" or "lazy" Item in a `FlexList`.
 * Lazy items are wrapped in a function to allow referring to themselves before they are declared.
 * This makes recursive and co-recursive items possible.
 * @public
 */
export declare type LazyItem<Item = unknown> = Item | (() => Item);

/* Excluded from this release type: LazyTreeNodeSchema */

/* Excluded from this release type: leaf */

/* Excluded from this release type: LeafNodeSchema */

/* Excluded from this release type: LeafNodeStoredSchema */

/* Excluded from this release type: LocalNodeKey */

/**
 * Utilities for manipulating the typescript typechecker.
 *
 * @remarks
 * While it appears the the variance parts of this library are made obsolete by TypeScript 4.7's explicit variance annotations,
 * many cases still type check with incorrect variance even when using the explicit annotations,
 * and are fixed by using the patterns in this library.
 *
 * TypeScript uses structural typing if there are no private or protected members,
 * and variance of generic type parameters depends on their usages.
 * Thus when trying to constrain code by adding extra type information,
 * it often fails to actually constrain as desired, and these utilities can help with those cases.
 *
 * This library is designed so that the desired variance can be documented in a way that is easy to read, concise,
 * and allows easy navigation to documentation explaining what is being done
 * for readers who are not familiar with this library.
 * Additionally it constrains the types so the undesired usage patterns will not compile,
 * and will give somewhat intelligible errors.
 *
 * Additionally this library provides the tools needed to test that the type constraints are working as expected,
 * or test any other similar typing constraints in an application.
 *
 * This library assumes you are compiling with --strictFunctionTypes:
 * (Covariance and Contravariance is explained along with how these helpers cause it in typescript at this link)
 * {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html#strict-function-types}.
 * If compiled with a TypeScript configuration that is not strict enough for these features to work,
 * the test suite should fail to build.
 *
 * Classes in TypeScript by default allow all assignments:
 * its only though adding members that any type constraints actually get applied.
 * This library provides types that can be used on a protected member of a class to add the desired constraints.
 *
 * Typical usages (use one field like this at the top of a class):
 * ```typescript
 * protected _typeCheck?: MakeNominal;
 * protected _typeCheck?: Contravariant<T>;
 * protected _typeCheck?: Covariant<T>;
 * protected _typeCheck?: Invariant<T>;
 * protected _typeCheck?: Contravariant<T> & Invariant<K>;
 * ```
 *
 * See tests for examples.
 *
 * Note that all of these cause nominal typing.
 * If constraints on generic type parameter variance are desired, but nominal typing is not,
 * these types can be used on a public field. This case also works with interfaces.
 *
 * Be aware that other members of your type might apply further constraints
 * (ex: you might try and write a Contravariant<T> class, but it ends up being Invariant<T> due to a field of type T).
 *
 * Be aware of TypeScript Bug:
 * {@link https://github.com/microsoft/TypeScript/issues/36906}.
 * This bug is why the fields here are protected not private.
 * Note that this bug is closed as a duplicate of {@link https://github.com/microsoft/TypeScript/issues/20979}
 * which was closed because fixing it would be too large of a breaking change.
 * Thus we expect this bug to be part of TypeScript for the forseeable future.
 */
/**
 * Use this as the type of a protected field to cause a type to use nominal typing instead of structural.
 *
 * @remarks
 * Using nominal typing in this way prevents assignment of objects which are not instances of this class to values of this class's type.
 * Classes which are used with "instanceof", or are supposed to be instantiated in particular ways (not just made with object literals)
 * can use this to prevent undesired assignments.
 * @example
 * ```typescript
 * protected _typeCheck?: MakeNominal;
 * ```
 * @privateRemarks
 * See: {@link https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types}
 * @public
 */
export declare interface MakeNominal {
}

/* Excluded from this release type: MapNodeStoredSchema */

/* Excluded from this release type: MapTree */

/* Excluded from this release type: MarkedArrayLike */

/* Excluded from this release type: Multiplicity */

/* Excluded from this release type: Named */

/* Excluded from this release type: NameFromBranded */

/* Excluded from this release type: NestedMap */

/* Excluded from this release type: NewFieldContent */

/**
 * Given a node's schema, return the corresponding object from which the node could be built.
 * @privateRemarks
 * Currently this assumes factory functions take exactly one argument.
 * This could be changed if needed.
 *
 * These factory functions can also take a FlexTreeNode, but this is not exposed in the public facing types.
 * @public
 */
export declare type NodeBuilderData<T extends TreeNodeSchema> = T extends TreeNodeSchema<string, NodeKind, unknown, infer TBuild> ? TBuild : never;

/* Excluded from this release type: NodeBuilderDataUnsafe */

/* Excluded from this release type: NodeData */

/* Excluded from this release type: NodeExistsConstraint */

/**
 * Takes in `TreeNodeSchema[]` and returns a TypedNode union.
 * @public
 */
export declare type NodeFromSchema<T extends TreeNodeSchema> = T extends TreeNodeSchema<string, NodeKind, infer TNode> ? TNode : never;

/* Excluded from this release type: NodeFromSchemaUnsafe */

/* Excluded from this release type: NodeIndex */

/* Excluded from this release type: nodeKeyFieldKey */

/* Excluded from this release type: NodeKeyFieldKind */

/* Excluded from this release type: NodeKeys */

/**
 * Kind of tree node.
 * @public
 */
export declare enum NodeKind {
    /**
     * A node which serves as a map, storing children under string keys.
     */
    Map = 0,
    /**
     * A node which serves as an array, storing children in an ordered sequence.
     */
    Array = 1,
    /**
     * A node which stores a heterogenous collection of children in named fields.
     * @remarks
     * Each field gets its own schema.
     */
    Object = 2,
    /**
     * A node which stores a single leaf value.
     */
    Leaf = 3
}

/* Excluded from this release type: NoListenersCallback */

/* Excluded from this release type: noopValidator */

/* Excluded from this release type: NormalizeAllowedTypes */

/* Excluded from this release type: NormalizeField */

/* Excluded from this release type: NormalizeFieldSchema */

/* Excluded from this release type: NormalizeObjectNodeFields */

/**
 * Helper used to produce types for object nodes.
 * @public
 */
export declare type ObjectFromSchemaRecord<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>> = {
    -readonly [Property in keyof T]: TreeFieldFromImplicitField<T[Property]>;
};

/* Excluded from this release type: ObjectFromSchemaRecordUnsafe */

/* Excluded from this release type: ObjectNodeStoredSchema */

/* Excluded from this release type: oneFromSet */

/* Excluded from this release type: Opaque */

/* Excluded from this release type: Optional */

/* Excluded from this release type: OptionalFieldEditBuilder */

/* Excluded from this release type: OptionalFields */

/* Excluded from this release type: PathRootPrefix */

/* Excluded from this release type: PathVisitor */

/* Excluded from this release type: PlaceIndex */

/* Excluded from this release type: PlaceUpPath */

/* Excluded from this release type: prefixFieldPath */

/* Excluded from this release type: prefixPath */

/* Excluded from this release type: PropertyNameFromFieldKey */

/* Excluded from this release type: ProtoNodes */

/* Excluded from this release type: Range_2 */

/* Excluded from this release type: RangeQueryResult */

/* Excluded from this release type: RangeUpPath */

/* Excluded from this release type: _RecursiveTrick */

/* Excluded from this release type: Required_2 */

/* Excluded from this release type: RequiredFields */

/* Excluded from this release type: ReservedObjectNodeFieldPropertyNamePrefixes */

/* Excluded from this release type: reservedObjectNodeFieldPropertyNamePrefixes */

/* Excluded from this release type: ReservedObjectNodeFieldPropertyNames */

/* Excluded from this release type: reservedObjectNodeFieldPropertyNames */

/**
 * Alternative to the built in Record type which does not permit unexpected members,
 * and is readonly.
 *
 * @privateRemarks
 * `number` is not allowed as a key here since doing so causes the compiler to reject recursive schema.
 * The cause for this is unclear, but empirically it was the case when this comment was written.
 * @public
 */
export declare type RestrictiveReadonlyRecord<K extends symbol | string, T> = {
    readonly [P in symbol | string]: P extends K ? T : never;
};

/**
 * Allows reversion of a change made to SharedTree.
 *
 * @remarks
 * Applications wanting to implement undo/redo support might typically maintain two stacks of Revertibles, with optional eviction policy to free up memory.
 *
 * @public
 */
export declare interface Revertible {
    /**
     * The current status of the revertible.
     */
    readonly status: RevertibleStatus;
    /**
     * Reverts the associated change.
     */
    revert(): void;
    /**
     * Releases this revertible so that it can no longer be used.
     */
    release(): void;
}

/**
 * The status of a {@link Revertible}.
 *
 * @public
 */
export declare enum RevertibleStatus {
    /** The revertible can be reverted. */
    Valid = 0,
    /** The revertible has been disposed. Reverting it will have no effect. */
    Disposed = 1
}

/* Excluded from this release type: RevisionTag */

/* Excluded from this release type: RootField */

/* Excluded from this release type: rootField */

/* Excluded from this release type: rootFieldKey */

/* Excluded from this release type: runSynchronous */

/* Excluded from this release type: SchemaBuilderBase */

/* Excluded from this release type: SchemaBuilderOptions */

/* Excluded from this release type: SchemaCollection */

/* Excluded from this release type: SchemaConfiguration */

/* Excluded from this release type: SchemaEvents */

/**
 * Creates various types of {@link TreeNodeSchema|schema} for {@link TreeNode}s.
 *
 * @typeParam TScope - Scope added as a prefix to the name of every schema produced by this factory.
 * @typeParam TName - Type of names used to identify each schema produced in this factory.
 * Typically this is just `string` but it is also possible to use `string` or `number` based enums if you prefer to identify your types that way.
 *
 * @remarks
 * All schema produced by this factory get a {@link TreeNodeSchemaCore.identifier|unique identifier} by {@link ScopedSchemaName|combining} the {@link SchemaFactory.scope} with the schema's `Name`.
 * The `Name` part may be explicitly provided as a parameter, or inferred as a structural combination of the provided types.
 * The APIs which use this second approach, structural naming, also deduplicate all equivalent calls.
 * Therefor two calls to `array(allowedTypes)` with the same allowedTypes will return the same {@link TreeNodeSchema} instance.
 * On the other hand, two calls to `array(name, allowedTypes)` will always return different {@link TreeNodeSchema} instances
 * and it is an error to use both in the same tree (since their identifiers are not unique).
 *
 * Note:
 * POJO stands for Plain Old JavaScript Object.
 * This means an object that works like a `{}` style object literal.
 * In this case it means the prototype is `Object.prototype` and acts like a set of key value pairs (data, not methods).
 * The usage below generalizes this to include array and map like objects as well.
 *
 * There are two ways to use these APIs:
 * |                     | Customizable | POJO Emulation |
 * | ------------------- | ------------ |--------------- |
 * | Declaration         | `class X extends schemaFactory.object("x", {}) {}` | `const X = schemaFactory.object("x", {}); type X = NodeFromSchema<typeof X>; `
 * | Allows adding "local" (non-persisted) members | Yes. Members (including methods) can be added to class.        | No. Attempting to set non-field members will error. |
 * | Prototype | The user defined class | `Object.prototype`, `Map.prototype` or `Array.prototype` depending on node kind |
 * | Structurally named Schema | Not Supported | Supported |
 * | Explicitly named Objects | Supported | Supported |
 * | Explicitly named Maps and Arrays | Supported: Both declaration approaches can be used | Not Supported |
 * | node.js assert.deepEqual | Compares like class instances: equal to other nodes of the same type with the same content, including custom local fields. | Compares like plain objects: equal to plain JavaScript objects with the same fields, and other nodes with the same fields, even if the types are different. |
 * | IntelliSense | Shows and links to user defined class by name: `X` | Shows internal type generation logic: `object & TreeNode & ObjectFromSchemaRecord<{}> & WithType<"test.x">` |
 * | Recursion | Supported with special declaration patterns. | Unsupported: Generated d.ts files replace recursive references with `any`, breaking use of recursive schema across compilation boundaries |
 *
 * Note that while "POJO Emulation" nodes act a lot like POJO objects, they are not true POJO objects:
 *
 * - Adding new arbitrary fields will error, as well some cases of invalid edits.
 *
 * - They are implemented using proxies.
 *
 * - They have state that is not exposed via enumerable own properties, including a {@link TreeNodeSchema}.
 * This makes libraries like node.js `assert.deepEqual` fail to detect differences in type.
 *
 * - Assigning members has side effects (in this case editing the persisted/shared tree).
 *
 * - Not all operations implied by the prototype will work correctly: stick to the APIs explicitly declared in the TypeScript types.
 *
 * @privateRemarks
 * It's perfectly possible to make `POJO Emulation` mode (or even just hiding the prototype) selectable even when using the custom user class declaration syntax.
 * When doing this, it's still possible to make `instanceof` perform correctly.
 * Allowing (or banning) custom/out-of-schema properties on the class is also possible in both modes: it could be orthogonal.
 * Also for consistency, if keeping the current approach to detecting `POJO Emulation` mode it might make sense to make explicitly named Maps and Arrays do the detection the same as how object does it.
 *
 * @sealed @public
 */
export declare class SchemaFactory<out TScope extends string | undefined = string | undefined, TName extends number | string = string> {
    readonly scope: TScope;
    private readonly structuralTypes;
    /**
     * @param scope - Prefix appended to the identifiers of all {@link TreeNodeSchema} produced by this builder.
     * Use of [Reverse domain name notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation) or a UUIDv4 is recommended to avoid collisions.
     * You may opt out of using a scope by passing `undefined`, but note that this increases the risk of collisions.
     */
    constructor(scope: TScope);
    private scoped;
    /**
     * {@link TreeNodeSchema} for holding a JavaScript `string`.
     *
     * @remarks
     * Strings containing unpaired UTF-16 surrogate pair code units may not be handled correctly.
     *
     * These limitations come from the use of UTF-8 encoding of the strings, which requires them to be valid unicode.
     * JavaScript does not make this requirement for its strings so not all possible JavaScript strings are supported.
     * @privateRemarks
     * TODO:
     * We should be much more clear about what happens if you use problematic values.
     * We should validate and/or normalize them when inserting content.
     */
    readonly string: TreeNodeSchema<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string>;
    /**
     * {@link TreeNodeSchema} for holding a JavaScript `number`.
     *
     * @remarks
     * The number is a [double-precision 64-bit binary format IEEE 754](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) value, however there are some exceptions:
     * - `NaN`, and the infinities are converted to `null` (and may therefore only be used where `null` is allowed by the schema).
     * - `-0` may be converted to `0` in some cases.
     *
     * These limitations match the limitations of JSON.
     * @privateRemarks
     * TODO:
     * We should be much more clear about what happens if you use problematic values.
     * We should validate and/or normalize them when inserting content.
     */
    readonly number: TreeNodeSchema<"com.fluidframework.leaf.number", NodeKind.Leaf, number, number>;
    /**
     * {@link TreeNodeSchema} for holding a boolean.
     */
    readonly boolean: TreeNodeSchema<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean>;
    /**
     * {@link TreeNodeSchema} for JavaScript `null`.
     *
     * @remarks
     * There are good [reasons to avoid using null](https://www.npmjs.com/package/%40rushstack/eslint-plugin#rushstackno-new-null) in JavaScript, however sometimes it is desired.
     * This {@link TreeNodeSchema} node provides the option to include nulls in trees when desired.
     * Unless directly inter-operating with existing data using null, consider other approaches, like wrapping the value in an optional field, or using a more specifically named empty object node.
     */
    readonly null: TreeNodeSchema<"com.fluidframework.leaf.null", NodeKind.Leaf, null, null>;
    /**
     * {@link TreeNodeSchema} for holding an {@link @fluidframework/core-interfaces#(IFluidHandle:interface)}.
     */
    readonly handle: TreeNodeSchema<"com.fluidframework.leaf.handle", NodeKind.Leaf, IFluidHandle<FluidObject<unknown> & IFluidLoadable>, IFluidHandle<FluidObject<unknown> & IFluidLoadable>>;
    /**
     * Construct a class that provides the common parts all TreeNodeSchemaClass share.
     * More specific schema extend this class.
     */
    private nodeSchema;
    /**
     * Define a {@link TreeNodeSchema} 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.
     */
    object<const Name extends TName, const T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>>(name: Name, fields: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNode<T, ScopedSchemaName<TScope, Name>>, object & InsertableObjectFromSchemaRecord<T>, true, T>;
    /**
     * Define a structurally typed {@link TreeNodeSchema} for a {@link TreeMapNode}.
     *
     * @remarks
     * The unique identifier for this Map is defined as a function of the provided types.
     * It is still scoped to this SchemaBuilder, but multiple calls with the same arguments will return the same schema object, providing somewhat structural typing.
     * This does not support recursive types.
     *
     * If using these structurally named maps, other types in this schema builder should avoid names of the form `Map<${string}>`.
     *
     * @example
     * The returned schema should be used as a schema directly:
     * ```typescript
     * const MyMap = factory.map(factory.number);
     * type MyMap = NodeFromSchema<typeof MyMap>;
     * ```
     * Or inline:
     * ```typescript
     * factory.object("Foo", {myMap: factory.map(factory.number)});
     * ```
     * @privateRemarks
     * See note on array.
     */
    map<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>>, Iterable<[string, InsertableTreeNodeFromImplicitAllowedTypes<T>]>, true, T>;
    /**
     * Define a {@link TreeNodeSchema} for a {@link TreeMapNode}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     *
     * @example
     * ```typescript
     * class NamedMap extends factory.map("name", factory.number) {}
     * ```
     */
    map<Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>>, Iterable<[string, InsertableTreeNodeFromImplicitAllowedTypes<T>]>, true, T>;
    /**
     * Define a {@link TreeNodeSchema} for a {@link (TreeMapNode:interface)}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     *
     * @remarks See remarks on {@link SchemaFactory.namedArray_internal}.
     */
    namedMap_internal<Name extends TName | string, const T extends ImplicitAllowedTypes, const ImplicitlyConstructable extends boolean>(name: Name, allowedTypes: T, customizable: boolean, implicitlyConstructable: ImplicitlyConstructable): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>>, Iterable<[string, InsertableTreeNodeFromImplicitAllowedTypes<T>]>, ImplicitlyConstructable, T>;
    /**
     * Define a structurally typed {@link TreeNodeSchema} for a {@link (TreeArrayNode:interface)}.
     *
     * @remarks
     * The identifier for this Array is defined as a function of the provided types.
     * It is still scoped to this SchemaFactory, but multiple calls with the same arguments will return the same schema object, providing somewhat structural typing.
     * This does not support recursive types.
     *
     * If using these structurally named arrays, other types in this schema builder should avoid names of the form `Array<${string}>`.
     *
     * @example
     * The returned schema should be used as a schema directly:
     * ```typescript
     * const MyArray = factory.array(factory.number);
     * type MyArray = NodeFromSchema<typeof MyArray>;
     * ```
     * Or inline:
     * ```typescript
     * factory.object("Foo", {myArray: factory.array(factory.number)});
     * ```
     * @privateRemarks
     * The name produced at the type level here is not as specific as it could be, however doing type level sorting and escaping is a real mess.
     * There are cases where not having this full type provided will be less than ideal since TypeScript's structural types.
     * For example attempts to narrow unions of structural arrays by name won't work.
     * Planned future changes to move to a class based schema system as well as factor function based node construction should mostly avoid these issues,
     * though there may still be some problematic cases even after that work is done.
     *
     * The return value is a class, but its the type is intentionally not specific enough to indicate it is a class.
     * This prevents callers of this from sub-classing it, which is unlikely to work well (due to the ease of accidentally giving two different calls o this different subclasses)
     * when working with structural typing.
     *
     * {@label STRUCTURAL}
     */
    array<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
    /**
     * Define (and add to this library) a {@link TreeNodeSchemaClass} for a {@link (TreeArrayNode:interface)}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     *
     * @example
     * ```typescript
     * class NamedArray extends factory.array("name", factory.number) {}
     * ```
     *
     * {@label NAMED}
     */
    array<const Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, Name>>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
    /**
     * Define a {@link TreeNodeSchema} for a {@link (TreeArrayNode:interface)}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     *
     * @remarks
     * This is not intended to be used directly, use the overload of `array` which takes a name instead.
     * This is only public to work around a compiler limitation.
     *
     * @privateRemarks
     * TODO: this should be made private or protected.
     * Doing so breaks due to:
     * `src/class-tree/schemaFactoryRecursive.ts:42:9 - error TS2310: Type 'Array' recursively references itself as a base type.`
     * Once recursive APIs are better sorted out and integrated into this class, switch this back to private.
     */
    namedArray_internal<Name extends TName | string, const T extends ImplicitAllowedTypes, const ImplicitlyConstructable extends boolean>(name: Name, allowedTypes: T, customizable: boolean, implicitlyConstructable: ImplicitlyConstructable): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, string>>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, ImplicitlyConstructable, T>;
    /**
     * Make a field optional instead of the default, which is required.
     *
     * @param t - The types allowed under the field.
     * @param props - Optional properties to associate with the field.
     */
    optional<const T extends ImplicitAllowedTypes>(t: T, props?: FieldProps): FieldSchema<FieldKind.Optional, T>;
    /**
     * Make a field explicitly required.
     *
     * @param t - The types allowed under the field.
     * @param props - Optional properties to associate with the field.
     *
     * @remarks
     * Fields are required by default, but this API can be used to make the required nature explicit in the schema,
     * and allows associating custom {@link FieldProps | properties} with the field.
     */
    required<const T extends ImplicitAllowedTypes>(t: T, props?: FieldProps): FieldSchema<FieldKind.Required, T>;
    /**
     * Function which can be used for its compile time side-effects to tweak the evaluation order of recursive types to make them compile.
     * @remarks
     * Some related information in https://github.com/microsoft/TypeScript/issues/55758.
     *
     * Also be aware that code which relies on this tends to break VSCode's IntelliSense every time anything related to that code (even comments) is edited.
     * Running the command `TypeScript: Restart TS Server` with the schema file focused should fix it.
     * Sometimes this does not work: closing all open files except the schema before running the command can help.
     * Real compile errors (for example elsewhere in the file) can also cause the IntelliSense to not work correctly ever after `TypeScript: Restart TS Server`.
     *
     * Intellisense has also shown problems when schema files with recursive types are part of a cyclic file dependency.
     * Splitting the schema into its own file with minimal dependencies can help with this.
     *
     * Ensure `"noImplicitAny": true` is set in the `tsconfig.json`.
     * Without it, recursive types that are not working properly can infer `any` and give very non-type-safe results instead of erroring.
     *
     * @example
     * ```typescript
     * const factory = new SchemaFactory("example");
     * const recursiveReference = () => RecursiveObject;
     * factory.fixRecursiveReference(recursiveReference);
     * export class RecursiveObject extends factory.object("exampleObject", {
     * 	recursive: [recursiveReference],
     * }) {}
     * ```
     * @deprecated Use special `recursive` versions of builders instead of relying on this.
     */
    fixRecursiveReference<T extends AllowedTypes>(...types: T): void;
}

/* Excluded from this release type: SchemaFactoryRecursive */

/**
 * Information about how a view schema was incompatible.
 * @public
 */
export declare interface SchemaIncompatible {
    /**
     * True iff the view schema supports all possible documents permitted by the stored schema.
     *
     * @remarks
     * When true, this is still an error because the view schema supports more documents than the stored schema.
     * This means that writes to the document using the view schema could make the document violate its stored schema.
     * In this case, the stored schema could be updated to match the provided view schema, allowing read write access to the tree.
     *
     * Future version of SharedTree may provide readonly access to the document in this case because that would be safe:
     * but this is not currently supported.
     */
    readonly canUpgrade: boolean;
}

/* Excluded from this release type: schemaIsFieldNode */

/* Excluded from this release type: schemaIsLeaf */

/* Excluded from this release type: schemaIsMap */

/* Excluded from this release type: schemaIsObjectNode */

/* Excluded from this release type: SchemaLibrary */

/* Excluded from this release type: SchemaLibraryData */

/* Excluded from this release type: SchemaLintConfiguration */

/* Excluded from this release type: SchematizeConfiguration */

/* Excluded from this release type: SchemaValidationFunction */

/**
 * The name of a schema produced by {@link SchemaFactory}, including its optional scope prefix.
 *
 * @public
 */
export declare type ScopedSchemaName<TScope extends string | undefined, TName extends number | string> = TScope extends undefined ? `${TName}` : `${TScope}.${TName}`;

/* Excluded from this release type: Sequence */

/* Excluded from this release type: SequenceFieldEditBuilder */

/**
 * SharedTree is a hierarchical data structure for collaboratively editing strongly typed JSON-like trees
 * of objects, arrays, and other data types.
 * @public
 */
export declare const SharedTree: ISharedObjectKind<ITree>;

/* Excluded from this release type: SharedTreeContentSnapshot */

/* Excluded from this release type: SharedTreeFactory */

/* Excluded from this release type: SharedTreeFormatOptions */

/* Excluded from this release type: SharedTreeFormatVersion */

/* Excluded from this release type: SharedTreeOptions */

/* Excluded from this release type: singletonSchema */

/* Excluded from this release type: StableNodeKey */

/* Excluded from this release type: stackTreeFieldCursor */

/* Excluded from this release type: stackTreeNodeCursor */

/* Excluded from this release type: StoredSchemaCollection */

/* Excluded from this release type: test_RecursiveObject */

/* Excluded from this release type: test_RecursiveObject_base */

/* Excluded from this release type: test_RecursiveObjectPojoMode */

/* Excluded from this release type: TransactionResult */

/**
 * The `Tree` object holds various functions for interacting with {@link TreeNode}s.
 * @public
 */
export declare const Tree: TreeApi;

/* Excluded from this release type: TreeAdapter */

/**
 * Provides various functions for interacting with {@link TreeNode}s.
 * @public
 */
export declare interface TreeApi extends TreeNodeApi {
    /**
     * Apply one or more edits to the tree as a single atomic unit.
     * @param node - The node that will be passed to `transaction`.
     * This is typically the root node of the subtree that will be modified by the transaction.
     * @param transaction - The function to run as the body of the transaction.
     * This function is passed the provided `node`.
     * At any point during the transaction, the function may return the value `"rollback"` to abort the transaction and discard any changes it made so far.
     * @remarks
     * All of the changes in the transaction are applied synchronously and therefore no other changes (either from this client or from a remote client) can be interleaved with those changes.
     * Note that this is guaranteed by Fluid for any sequence of changes that are submitted synchronously, whether in a transaction or not.
     * However, using a transaction has the following additional consequences:
     * - If reverted (e.g. via an "undo" operation), all the changes in the transaction are reverted together.
     * - The internal data representation of a transaction with many changes is generally smaller and more efficient than that of the changes when separate.
     *
     * Local change events will be emitted for each change as the transaction is being applied.
     * If the transaction is cancelled and rolled back, a corresponding change event will also be emitted for the rollback.
     */
    runTransaction<TNode extends TreeNode>(node: TNode, transaction: (node: TNode) => void | "rollback"): void;
    /**
     * Apply one or more edits to the tree as a single atomic unit.
     * @param tree - The tree which will be edited by the transaction
     * @param transaction - The function to run as the body of the transaction.
     * This function is passed the root of the tree.
     * At any point during the transaction, the function may return the value `"rollback"` to abort the transaction and discard any changes it made so far.
     * @remarks
     * All of the changes in the transaction are applied synchronously and therefore no other changes (either from this client or from a remote client) can be interleaved with those changes.
     * Note that this is guaranteed by Fluid for any sequence of changes that are submitted synchronously, whether in a transaction or not.
     * However, using a transaction has the following additional consequences:
     * - If reverted (e.g. via an "undo" operation), all the changes in the transaction are reverted together.
     * - The internal data representation of a transaction with many changes is generally smaller and more efficient than that of the changes when separate.
     *
     * Local change events will be emitted for each change as the transaction is being applied.
     * If the transaction is cancelled and rolled back, a corresponding change event will also be emitted for the rollback.
     */
    runTransaction<TRoot>(tree: TreeView<TRoot>, transaction: (root: TRoot) => void | "rollback"): void;
}

/**
 * A {@link TreeNode} which implements 'readonly T[]' and the array mutation APIs.
 *
 * @typeParam TAllowedTypes - Schema for types which are allowed as members of this array.
 *
 * @public
 */
export declare interface TreeArrayNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeArrayNodeBase<TreeNodeFromImplicitAllowedTypes<TAllowedTypes>, InsertableTreeNodeFromImplicitAllowedTypes<TAllowedTypes>, TreeArrayNode> {
}

/**
 * A {@link TreeNode} which implements 'readonly T[]' and the array mutation APIs.
 * @public
 */
export declare const TreeArrayNode: {
    /**
     * Wrap an iterable of items to inserted as consecutive items in a array.
     * @remarks
     * The object returned by this function can be inserted into a {@link (TreeArrayNode:interface)}.
     * Its contents will be inserted consecutively in the corresponding location in the array.
     * @example
     * ```ts
     * array.insertAtEnd(TreeArrayNode.spread(iterable))
     * ```
     */
    spread: <T>(content: Iterable<T>) => IterableTreeArrayContent<T>;
};

/**
 * A generic array type, used to defined types like {@link (TreeArrayNode:interface)}.
 *
 * @privateRemarks
 * Inlining this into TreeArrayNode causes recursive array use to stop compiling.
 *
 * @public
 */
export declare interface TreeArrayNodeBase<out T, in TNew, in TMoveFrom> extends ReadonlyArray<T>, TreeNode {
    /**
     * Inserts new item(s) at a specified location.
     * @param index - The index at which to insert `value`.
     * @param value - The content to insert.
     * @throws Throws if `index` is not in the range [0, `array.length`).
     */
    insertAt(index: number, ...value: (TNew | IterableTreeArrayContent<TNew>)[]): void;
    /**
     * Inserts new item(s) at the start of the array.
     * @param value - The content to insert.
     */
    insertAtStart(...value: (TNew | IterableTreeArrayContent<TNew>)[]): void;
    /**
     * Inserts new item(s) at the end of the array.
     * @param value - The content to insert.
     */
    insertAtEnd(...value: (TNew | IterableTreeArrayContent<TNew>)[]): void;
    /**
     * Removes the item at the specified location.
     * @param index - The index at which to remove the item.
     * @throws Throws if `index` is not in the range [0, `array.length`).
     */
    removeAt(index: number): void;
    /**
     * Removes all items between the specified indices.
     * @param start - The starting index of the range to remove (inclusive). Defaults to the start of the array.
     * @param end - The ending index of the range to remove (exclusive).
     * @throws Throws if `start` is not in the range [0, `array.length`).
     * @throws Throws if `end` is less than `start`.
     * If `end` is not supplied or is greater than the length of the array, all items after `start` are removed.
     */
    removeRange(start?: number, end?: number): void;
    /**
     * Moves the specified item to the start of the array.
     * @param sourceIndex - The index of the item to move.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToStart(sourceIndex: number): void;
    /**
     * Moves the specified item to the start of the array.
     * @param sourceIndex - The index of the item to move.
     * @param source - The source array to move the item out of.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToStart(sourceIndex: number, source: TMoveFrom): void;
    /**
     * Moves the specified item to the end of the array.
     * @param sourceIndex - The index of the item to move.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToEnd(sourceIndex: number): void;
    /**
     * Moves the specified item to the end of the array.
     * @param sourceIndex - The index of the item to move.
     * @param source - The source array to move the item out of.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToEnd(sourceIndex: number, source: TMoveFrom): void;
    /**
     * Moves the specified item to the desired location in the array.
     * @param index - The index to move the item to.
     * This is based on the state of the array before moving the source item.
     * @param sourceIndex - The index of the item to move.
     * @throws Throws if any of the input indices are not in the range [0, `array.length`).
     */
    moveToIndex(index: number, sourceIndex: number): void;
    /**
     * Moves the specified item to the desired location in the array.
     * @param index - The index to move the item to.
     * @param sourceIndex - The index of the item to move.
     * @param source - The source array to move the item out of.
     * @throws Throws if any of the input indices are not in the range [0, `array.length`).
     */
    moveToIndex(index: number, sourceIndex: number, source: TMoveFrom): void;
    /**
     * Moves the specified items to the start of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @throws Throws if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToStart(sourceStart: number, sourceEnd: number): void;
    /**
     * Moves the specified items to the start of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @param source - The source array to move items out of.
     * @throws Throws if the types of any of the items being moved are not allowed in the destination array,
     * if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToStart(sourceStart: number, sourceEnd: number, source: TMoveFrom): void;
    /**
     * Moves the specified items to the end of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @throws Throws if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToEnd(sourceStart: number, sourceEnd: number): void;
    /**
     * Moves the specified items to the end of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @param source - The source array to move items out of.
     * @throws Throws if the types of any of the items being moved are not allowed in the destination array,
     * if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToEnd(sourceStart: number, sourceEnd: number, source: TMoveFrom): void;
    /**
     * Moves the specified items to the desired location within the array.
     * @param index - The index to move the items to.
     * This is based on the state of the array before moving the source items.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @throws Throws if any of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToIndex(index: number, sourceStart: number, sourceEnd: number): void;
    /**
     * Moves the specified items to the desired location within the array.
     * @param index - The index to move the items to.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @param source - The source array to move items out of.
     * @throws Throws if the types of any of the items being moved are not allowed in the destination array,
     * if any of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToIndex(index: number, sourceStart: number, sourceEnd: number, source: TMoveFrom): void;
}

/* Excluded from this release type: TreeArrayNodeUnsafe */

/**
 * A collection of events that can be raised by a {@link TreeNode}.
 *
 * @privateRemarks
 * TODO: add a way to subscribe to a specific field (for nodeChanged and treeChanged).
 * Probably have object node and map node specific APIs for this.
 *
 * TODO: ensure that subscription API for fields aligns with API for subscribing to the root.
 *
 * TODO: add more wider area (avoid needing tons of nodeChanged registration) events for use-cases other than treeChanged.
 * Some ideas:
 *
 * - treeChanged, but with some subtrees/fields/paths excluded
 * - helper to batch several nodeChanged calls to a treeChanged scope
 * - parent change (ex: registration on the parent field for a specific index: maybe allow it for a range. Ex: node event takes optional field and optional index range?)
 * - new content inserted into subtree. Either provide event for this and/or enough info to treeChanged to find and search the new sub-trees.
 * Add separate (non event related) API to efficiently scan tree for given set of types (using low level cursor and schema based filtering)
 * to allow efficiently searching for new content (and initial content) of a given type.
 *
 * @public
 */
export declare interface TreeChangeEvents {
    /**
     * Emitted by a node when a batch of changes is applied to it, where a change is:
     *
     * - For an object node, when the value of one of its properties changes (i.e., the property's value is set
     * to something else, including `undefined`).
     *
     * - For an array node, when an element is added, removed, or moved.
     *
     * - For a map node, when an entry is added, updated, or removed.
     *
     * @remarks
     * This event is not raised when:
     *
     * - Properties of a child node change. Notably, updates to an array node or a map node (like adding or removing
     * elements/entries) will raise this event on the array/map node itself, but not on the node that contains the
     * array/map node as one of its properties.
     *
     * - The node is moved to a different location in the tree or removed from the tree.
     * In this case the event is raised on the _parent_ node, not the node itself.
     *
     * For remote edits, this event is not guaranteed to occur in the same order or quantity that it did in
     * the client that made the original edit.
     * While a batch of edits will as a whole update the tree to the appropriate end state, no guarantees are made about
     * how many times this event will be raised during any intermediate states.
     * When it is raised, the tree is guaranteed to be in-schema.
     *
     * @privateRemarks
     * This event occurs whenever the apparent contents of the node instance change, regardless of what caused the change.
     * For example, it will fire when the local client reassigns a child, when part of a remote edit is applied to the
     * node, or when the node has to be updated due to resolution of a merge conflict
     * (for example a previously applied local change might be undone, then reapplied differently or not at all).
     */
    nodeChanged(): void;
    /**
     * Emitted by a node when something _may_ have changed anywhere in the subtree rooted at it.
     *
     * @remarks
     * This event is guaranteed to be emitted whenever the subtree _has_ changed.
     * However, it might also be emitted when the subtree has no visible changes compared to before the event firing.
     *
     * Consumers of this event have the guarantee that they won't miss any changes, but should also handle the scenario
     * where the event fires with no visible changes as well.
     *
     * This event is not raised when the node itself is moved to a different location in the tree or removed from the tree.
     * In that case it is raised on the _parent_ node, not the node itself.
     *
     * The node itself is part of the subtree, so this event will be emitted even if the only changes are to the properties
     * of the node itself.
     *
     * For remote edits, this event is not guaranteed to occur in the same order or quantity that it did in
     * the client that made the original edit.
     * While a batch of edits will as a whole update the tree to the appropriate end state, no guarantees are made about
     * how many times this event will be raised during any intermediate states.
     * When it is raised, the tree is guaranteed to be in-schema.
     */
    treeChanged(): void;
}

/* Excluded from this release type: TreeCompressionStrategy */

/**
 * Configuration for how to {@link ITree.schematize|schematize} a tree.
 * @public
 */
export declare class TreeConfiguration<TSchema extends ImplicitFieldSchema = ImplicitFieldSchema> {
    readonly schema: TSchema;
    readonly initialTree: () => InsertableTreeFieldFromImplicitField<TSchema>;
    /**
     * @param schema - The schema which the application wants to view the tree with.
     * @param initialTree - A function that returns the default tree content to initialize the tree with iff the tree is uninitialized
     * (meaning it does not even have any schema set at all).
     * If `initialTree` returns any actual node instances, they should be recreated each time `initialTree` runs.
     * This is because if the config is used a second time any nodes that were not recreated could error since nodes cannot be inserted into the tree multiple times.
     */
    constructor(schema: TSchema, initialTree: () => InsertableTreeFieldFromImplicitField<TSchema>);
}

/* Excluded from this release type: TreeContent */

/* Excluded from this release type: TreeDataContext */

/**
 * Converts ImplicitFieldSchema to the corresponding tree node's field type.
 * @public
 */
export declare type TreeFieldFromImplicitField<TSchema extends ImplicitFieldSchema = FieldSchema> = TSchema extends FieldSchema<infer Kind, infer Types> ? ApplyKind<TreeNodeFromImplicitAllowedTypes<Types>, Kind> : TSchema extends ImplicitAllowedTypes ? TreeNodeFromImplicitAllowedTypes<TSchema> : unknown;

/* Excluded from this release type: TreeFieldFromImplicitFieldUnsafe */

/* Excluded from this release type: TreeFieldStoredSchema */

/**
 * Value that may be stored as a leaf node.
 * @public
 */
export declare type TreeLeafValue = number | string | boolean | IFluidHandle | null;

/* Excluded from this release type: TreeLocation */

/**
 * A map of string keys to tree objects.
 *
 * @privateRemarks
 * Add support for `clear` once we have established merge semantics for it.
 *
 * @public
 */
export declare interface TreeMapNode<T extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends ReadonlyMap<string, TreeNodeFromImplicitAllowedTypes<T>>, TreeNode {
    /**
     * Adds or updates an entry in the map with a specified `key` and a `value`.
     *
     * @param key - The key of the element to add to the map.
     * @param value - The value of the element to add to the map.
     *
     * @remarks
     * Setting the value at a key to `undefined` is equivalent to calling {@link TreeMapNode.delete} with that key.
     */
    set(key: string, value: InsertableTreeNodeFromImplicitAllowedTypes<T> | undefined): void;
    /**
     * Removes the specified element from this map by its `key`.
     *
     * @remarks
     * Note: unlike JavaScript's Map API, this method does not return a flag indicating whether or not the value was
     * deleted.
     *
     * @privateRemarks
     * Regarding the choice to not return a boolean: Since this data structure is distributed in nature, it isn't
     * possible to tell whether or not the item was deleted as a result of this method call. Returning a "best guess"
     * is more likely to create issues / promote bad usage patterns than offer useful information.
     *
     * @param key - The key of the element to remove from the map.
     */
    delete(key: string): void;
}

/* Excluded from this release type: TreeMapNodeUnsafe */

/* Excluded from this release type: TreeNavigationResult */

/**
 * A non-leaf SharedTree node. Includes objects, arrays, and maps.
 *
 * @remarks
 * Base type which all nodes implement.
 *
 * This can be used as a type to indicate/document values which should be tree nodes.
 * Runtime use of this class object (for example when used with `instanceof` or subclassed), is not supported:
 * it may be replaced with an interface or union in the future.
 * @privateRemarks
 * Future changes may replace this with a branded interface if the runtime oddities related to this are not cleaned up.
 *
 * Currently not all node implications include this in their prototype chain (some hide it with a proxy), and thus cause `instanceof` to fail.
 * This results in the runtime and compile time behavior of `instanceof` differing.
 * TypeScript 5.3 allows altering the compile time behavior of `instanceof`.
 * The runtime behavior can be changed by implementing `Symbol.hasInstance`.
 * One of those approaches could be used to resolve this inconsistency if TreeNode is kept as a class.
 * @public
 */
export declare abstract class TreeNode implements WithType {
    /**
     * This is added to prevent TypeScript from implicitly allowing non-TreeNode types to be used as TreeNodes.
     * @privateRemarks
     * This is a JavaScript private field, so is not accessible from outside this class.
     * This prevents it from having name collisions with object fields.
     * Since this is private, the type of this field is stripped in the d.ts file.
     * To get matching type checking within and from outside the package, the least informative type (`unknown`) is used.
     * To avoid this having any runtime impact, the field is uninitialized.
     *
     * Making this field optional results in different type checking within this project than outside of it, since the d.ts file drops the optional aspect of the field.
     * This is extra confusing since sin ce the tests get in-project typing for intellisense and separate project checking at build time.
     * To avoid all this mess, this field is required, not optional.
     *
     * Another option would be to use a symbol (possibly as a private field).
     * That approach ran into some strange difficulties causing SchemaFactory to fail to compile, and was not investigated further.
     *
     * TODO: This is disabled due to compilation of this project not targeting es2022,
     * which causes this to polyfill to use of a weak map which has some undesired runtime overhead.
     * Consider enabling this for stronger typing after targeting es2022.
     * The [type] symbol here provides a lot of the value this private brand would, but is not all of it:
     * someone could manually make an object literal with it and pass it off as a node: this private brand would prevent that.
     * Another option would be to add a protected or private symbol, which would also get the stronger typing.
     */
    /**
     * {@inheritdoc "type"}
     * @privateRemarks
     * Subclasses provide more specific strings for this to get strong typing of otherwise type compatible nodes.
     */
    abstract get [type](): string;
}

/**
 * Provides various functions for analyzing {@link TreeNode}s.
 *
 * @privateRemarks
 * Inlining the typing of this interface onto the `Tree` object provides slightly different .d.ts generation,
 * which avoids typescript expanding the type of TreeNodeSchema and thus encountering
 * https://github.com/microsoft/rushstack/issues/1958.
 * @public
 */
export declare interface TreeNodeApi {
    /**
     * The schema information for this node.
     */
    schema<T extends TreeNode | TreeLeafValue>(node: T): TreeNodeSchema<string, NodeKind, unknown, T>;
    /**
     * Narrow the type of the given value if it satisfies the given schema.
     * @example
     * ```ts
     * if (node.is(myNode, point)) {
     *     const y = myNode.y; // `myNode` is now known to satisfy the `point` schema and therefore has a `y` coordinate.
     * }
     * ```
     */
    is<TSchema extends TreeNodeSchema>(value: unknown, schema: TSchema): value is NodeFromSchema<TSchema>;
    /**
     * Return the node under which this node resides in the tree (or undefined if this is a root node of the tree).
     */
    parent(node: TreeNode): TreeNode | undefined;
    /**
     * The key of the given node under its parent.
     * @remarks
     * If `node` is an element in a {@link (TreeArrayNode:interface)}, this returns the index of `node` in the array node (a `number`).
     * Otherwise, this returns the key of the field that it is under (a `string`).
     */
    key(node: TreeNode): string | number;
    /**
     * Register an event listener on the given node.
     * @param node - The node whose events should be subscribed to.
     * @param eventName - Which event to subscribe to.
     * @param listener - The callback to trigger for the event. The tree can be read during the callback, but it is invalid to modify the tree during this callback.
     * @returns A callback function which will deregister the event.
     * This callback should be called only once.
     */
    on<K extends keyof TreeChangeEvents>(node: TreeNode, eventName: K, listener: TreeChangeEvents[K]): () => void;
    /**
     * Returns the {@link TreeStatus} of the given node.
     */
    readonly status: (node: TreeNode) => TreeStatus;
}

/**
 * Type of of tree node for a field of the given schema.
 * @public
 */
export declare type TreeNodeFromImplicitAllowedTypes<TSchema extends ImplicitAllowedTypes = TreeNodeSchema> = TSchema extends TreeNodeSchema ? NodeFromSchema<TSchema> : TSchema extends AllowedTypes ? NodeFromSchema<FlexListToUnion<TSchema>> : unknown;

/* Excluded from this release type: TreeNodeFromImplicitAllowedTypesUnsafe */

/**
 * Schema for a tree node.
 * @typeParam Name - The full (including scope) name/identifier for the schema.
 * @typeParam Kind - Which kind of node this schema is for.
 * @typeParam TNode - API for nodes that use this schema.
 * @typeParam TBuild - Data which can be used to construct an {@link Unhydrated} node of this type.
 * @typeParam Info - Data used when defining this schema.
 * @remarks
 * Captures the schema both as runtime data and compile time type information.
 * @public
 */
export declare type TreeNodeSchema<Name extends string = string, Kind extends NodeKind = NodeKind, TNode = unknown, TBuild = never, ImplicitlyConstructable extends boolean = boolean, Info = unknown> = TreeNodeSchemaClass<Name, Kind, TNode, TBuild, ImplicitlyConstructable, Info> | TreeNodeSchemaNonClass<Name, Kind, TNode, TBuild, ImplicitlyConstructable, Info>;

/* Excluded from this release type: TreeNodeSchemaBase */

/**
 * Tree node schema which is implemented using a class.
 * @remarks
 * Instances of this class are nodes in the tree.
 * This is also a constructor so that it can be subclassed.
 *
 * Using classes in this way allows introducing a named type and a named value at the same time, helping keep the runtime and compile time information together and easy to refer to un a uniform way.
 * Additionally, this works around https://github.com/microsoft/TypeScript/issues/55832 which causes similar patterns with less explicit types to infer "any" in the d.ts file.
 * @public
 */
export declare interface TreeNodeSchemaClass<out Name extends string = string, out Kind extends NodeKind = NodeKind, out TNode = unknown, in TInsertable = never, out ImplicitlyConstructable extends boolean = boolean, out Info = unknown> extends TreeNodeSchemaCore<Name, Kind, ImplicitlyConstructable, Info> {
    /**
     * Constructs an {@link Unhydrated} node with this schema.
     * @remarks
     * This constructor is also used internally to construct hydrated nodes with a different parameter type.
     * Therefor overriding this constructor is not type-safe and is not supported.
     * @sealed
     */
    new (data: TInsertable): Unhydrated<TNode>;
}

/**
 * Data common to all tree node schema.
 * @public
 */
export declare interface TreeNodeSchemaCore<out Name extends string, out Kind extends NodeKind, out ImplicitlyConstructable extends boolean, out Info = unknown> {
    readonly identifier: Name;
    readonly kind: Kind;
    /**
     * Data used to define this schema.
     *
     * @remarks
     * The format depends on the kind of node it is for.
     * For example, the "object" node kind could store the field schema here.
     */
    readonly info: Info;
    /**
     * When constructing insertable content,
     * data that could be passed to the node's constructor can be used instead of an {@link Unhydrated} node
     * iff implicitlyConstructable is true.
     * @privateRemarks
     * Currently the logic for traversing insertable content,
     * both to build trees and to hydrate them does not defer to the schema classes to handle the policy,
     * so if their constructors differ from what is supported, some cases will not work.
     * Setting this to false adjusts the insertable types to disallow cases which could be impacted by these inconsistencies.
     */
    readonly implicitlyConstructable: ImplicitlyConstructable;
}

/* Excluded from this release type: TreeNodeSchemaIdentifier */

/**
 * Schema which is not a class.
 * @remarks
 * This is used for schema which cannot have their instances constructed using constructors, like leaf schema.
 * @privateRemarks
 * Non-class based schema can have issues with recursive types due to https://github.com/microsoft/TypeScript/issues/55832.
 * @public
 */
export declare interface TreeNodeSchemaNonClass<out Name extends string = string, out Kind extends NodeKind = NodeKind, out TNode = unknown, in TInsertable = never, out ImplicitlyConstructable extends boolean = boolean, out Info = unknown> extends TreeNodeSchemaCore<Name, Kind, ImplicitlyConstructable, Info> {
    create(data: TInsertable): TNode;
}

/* Excluded from this release type: TreeNodeStoredSchema */

/**
 * A {@link TreeNode} which modules a JavaScript object.
 * @remarks
 * Object nodes consist of a type which specifies which {@link TreeNodeSchema} they use (see {@link TreeNodeApi.schema}), and a collections of fields, each with a distinct `key` and its own {@link FieldSchema} defining what can be placed under that key.
 *
 * All non-empty fields on an object node are exposed as enumerable own properties with string keys.
 * No other own `own` or `enumerable` properties are included on object nodes unless the user of the node manually adds custom session only state.
 * This allows a majority of general purpose JavaScript object processing operations (like `for...in`, `Reflect.ownKeys()` and `Object.entries()`) to enumerate all the children.
 * @public
 */
export declare type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName>;

/* Excluded from this release type: TreeObjectNodeUnsafe */

/* Excluded from this release type: treeSchemaFromStoredSchema */

/**
 * Status of the tree that a particular node belongs to.
 * @public
 */
export declare enum TreeStatus {
    /**
     * Is parented under the root field.
     */
    InDocument = 0,
    /**
     * Is not parented under the root field, but can be added back to the original document tree.
     */
    Removed = 1,
    /**
     * Is removed and cannot be added back to the original document tree.
     */
    Deleted = 2
}

/* Excluded from this release type: TreeStoredSchema */

/* Excluded from this release type: TreeStoredSchemaSubscription */

/* Excluded from this release type: TreeType */

/* Excluded from this release type: TreeTypeSet */

/* Excluded from this release type: TreeValue */

/**
 * An editable view of a (version control style) branch of a shared tree.
 *
 * This view is always in one of two states:
 * 1. In schema: the stored schema is compatible with the provided view schema. There is no error, and root can be used.
 * 2. Out of schema: the stored schema is incompatible with the provided view schema. There is an error, and root cannot be used.
 *
 * @privateRemarks
 * From an API design perspective, `upgradeSchema` could be merged into `schematize` anb/or `schematize` could return errors explicitly.
 * Such approaches would make it discoverable that out of schema handling may need to be done.
 * Doing that would however complicate trivial "hello world" style example slightly, as well as be a breaking API change.
 * It also seems more complex to handle invalidation with that pattern.
 * Thus this design was chosen at the risk of apps blindly accessing `root` then breaking unexpectedly when the document is incompatible.
 * If this does become a problem,
 * it could be mitigated by adding a `rootOrError` member and deprecating `root` to give users a warning if they might be missing the error checking.
 * @public
 */
export declare interface TreeView<in out TRoot> extends IDisposable {
    /**
     * The current root of the tree.
     *
     * If in the out of schema state, accessing this will throw.
     * To handle this case, check `error` before using.
     *
     * To get notified about changes to this field (including to it being in an `error` state),
     * use {@link TreeViewEvents.rootChanged} via `view.events.on("rootChanged", callback)`.
     */
    readonly root: TRoot;
    /**
     * Description of the error state, if any.
     * When this is undefined, the view schema and stored schema are compatible, and `root` can be used.
     */
    readonly error?: SchemaIncompatible;
    /**
     * When there is an `error` and {@link SchemaIncompatible.canUpgrade} is true,
     * this can be used to modify the stored schema to make it match the view schema.
     * This will clear the error state, and allow access to `root`.
     * @remarks
     * It is an error to call this when {@link SchemaIncompatible.canUpgrade} is false, and a no-op when not in an `error` state.
     * When this changes the stored schema, any existing or future clients which were compatible with the old stored schema will get an `error` state when trying to schematize the document.
     * @privateRemarks
     * In the future, more upgrade options could be provided here.
     * Some options that could be added:
     * - check the actual document contents (not just the schema) and attempt an atomic document update if the data is compatible.
     * - apply converters and upgrade the document.
     * - apply converters to lazily to adapt the document to the requested view schema (with optional lazy schema updates or transparent conversions on write).
     */
    upgradeSchema(): void;
    /**
     * Events for the tree.
     */
    readonly events: ISubscribable<TreeViewEvents>;
}

/**
 * Events for {@link TreeView}.
 * @public
 */
export declare interface TreeViewEvents {
    /**
     * A batch of changes has finished processing and the view has been updated.
     */
    afterBatch(): void;
    /**
     * {@link TreeView.root} has changed.
     * This includes going into or out of an `error` state where the root is unavailable due to stored schema changes.
     * It also includes changes to the field containing the root such as setting or clearing an optional root or changing which node is the root.
     * This does NOT include changes to the content (fields/children) of the root node: for that case subscribe to events on the root node.
     */
    rootChanged(): void;
    /**
     * Fired when a revertible made on this view is disposed.
     *
     * @param revertible - The revertible that was disposed.
     */
    revertibleDisposed(revertible: Revertible): void;
    /**
     * Fired when:
     * - a local commit is applied outside of a transaction
     * - a local transaction is committed
     *
     * The event is not fired when:
     * - a local commit is applied within a transaction
     * - a remote commit is applied
     *
     * @param data - information about the commit that was applied
     * @param getRevertible - a function provided that allows users to get a revertible for the commit that was applied. If not provided,
     * this commit is not revertible.
     */
    commitApplied(data: CommitMetadata, getRevertible?: () => Revertible): void;
}

/**
 * The type of a {@link TreeNode}.
 * For moore information about the type, use `Tree.schema(theNode)` instead.
 * @remarks
 * This symbol mainly exists on nodes to allow TypeScript to provide more accurate type checking.
 * `Tree.is` and `Tree.schema` provide a superset of this information in more friendly ways.
 *
 * This symbol should not manually be added to objects as doing so allows the object to be invalidly used where nodes are expected.
 * Instead construct a real node of the desired type using its constructor.
 * @privateRemarks
 * This prevents non-nodes from being accidentally used as nodes, as well as allows the type checker to distinguish different node types.
 * @public
 */
export declare const type: unique symbol;

/* Excluded from this release type: typeboxValidator */

/* Excluded from this release type: TypedFields */

/* Excluded from this release type: typedObjectValues */

/* Excluded from this release type: typeNameSymbol */

/* Excluded from this release type: UnbrandedName */

/* Excluded from this release type: Unenforced */

/**
 * Type alias to document which values are un-hydrated.
 *
 * Un-hydrated values are nodes produced from schema's create functions that haven't been inserted into a tree yet.
 *
 * Since un-hydrated nodes become hydrated when inserted, strong typing can't be used to distinguish them.
 * This no-op wrapper is used instead.
 * @public
 */
export declare type Unhydrated<T> = T;

/* Excluded from this release type: UpPath */

/* Excluded from this release type: UpPathDefault */

/* Excluded from this release type: ValidateRecursiveSchema */

/* Excluded from this release type: Value */

/* Excluded from this release type: ValueFieldEditBuilder */

/* Excluded from this release type: ValueFromBranded */

/* Excluded from this release type: ValueSchema */

/* Excluded from this release type: valueSymbol */

/**
 * Adds a {@link "type"} field.
 * @public
 */
export declare interface WithType<TName extends string = string> {
    /**
     * {@inheritdoc "type"}
     */
    get [type](): TName;
}

export { }
