/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import type { UnionToTuple } from "../../util/index.js";
import type { NodeKind, TreeNode, TreeNodeSchemaClass } from "../core/index.js";
import type { SchemaFactory, ScopedSchemaName } from "./schemaFactory.js";
import { SchemaFactoryBeta } from "./schemaFactoryBeta.js";
/**
 * Create a schema for a node with no state.
 * @remarks
 * This is commonly used in unions when the only information needed is which kind of node the value is.
 * Enums are a common example of this pattern.
 * @see {@link adaptEnum}
 * @beta
 */
export declare function singletonSchema<TScope extends string, TName extends string | number>(factory: SchemaFactory<TScope, TName>, name: TName): TreeNodeSchemaClass<ScopedSchemaName<TScope, TName>, NodeKind.Object, TreeNode & {
    readonly value: TName;
}, Record<string, never>, true, Record<string, never>, undefined>;
/**
 * Converts an enum into a collection of schema which can be used in a union.
 *
 * @typeParam TScope - The scope of the provided factory.
 * There is a known issue where if a factory is provided that is typed as a {@link SchemaFactoryAlpha}, and its scope contains a "." character,
 * the inferred type for the scope will end up as a union of the scope up to the first "." character and the scope as it should be.
 * This can be mitigated by explicitly providing the TScope type parameter or by typing the provided factory as a {@link SchemaFactory} instead of a {@link SchemaFactoryAlpha}.
 *
 * @remarks
 * The string value of the enum is used as the name of the schema: callers must ensure that it is stable and unique.
 * Numeric enums values have the value implicitly converted into a string.
 * Consider making a dedicated schema factory with a nested scope (for example using {@link SchemaFactoryBeta.scopedFactory}) to avoid the enum members colliding with other schema.
 * @example
 * ```typescript
 * const schemaFactory = new SchemaFactory("com.myApp");
 * // An enum for use in the tree. Must have string keys.
 * enum Mode {
 * 	a = "A",
 * 	b = "B",
 * }
 * // Define the schema for each member of the enum using a nested scope to group them together.
 * const ModeNodes = adaptEnum(new SchemaFactory(`${schemaFactory.scope}.Mode`), Mode);
 * // Defined the types of the nodes which correspond to this the schema.
 * type ModeNodes = TreeNodeFromImplicitAllowedTypes<(typeof ModeNodes.schema)>;
 * // An example schema which has an enum as a child.
 * class Parent extends schemaFactory.object("Parent", {
 * 	// adaptEnum's return value has a ".schema" property can be use as an `AllowedTypes` array allowing any of the members of the enum.
 * 	mode: ModeNodes.schema,
 * }) {}
 *
 * // Example usage of enum based nodes, showing what type to use and that `.value` can be used to read out the enum value.
 * function getValue(node: ModeNodes): Mode {
 * 	return node.value;
 * }
 *
 * // Example constructing a tree containing an enum node from an enum value.
 * // The syntax `new ModeNodes.a()` is also supported.
 * function setValue(node: Parent): void {
 * 	node.mode = ModeNodes(Mode.a);
 * }
 * ```
 * @privateRemarks
 * TODO: AB#43345: see TScope known issue above, and other references to this work item.
 *
 * @see {@link enumFromStrings} for a similar function that works on arrays of strings instead of an enum.
 * @beta
 */
export declare function adaptEnum<TScope extends string, const TEnum extends Record<string, string | number>>(factory: SchemaFactory<TScope>, members: TEnum): (<TValue extends TEnum[keyof TEnum]>(value: TValue) => TValue extends unknown ? TreeNode & {
    readonly value: TValue;
} : never) & { readonly [Property in keyof TEnum]: TreeNodeSchemaClass<ScopedSchemaName<TScope, TEnum[Property]>, NodeKind.Object, TreeNode & {
    readonly value: TEnum[Property];
}, Record<string, never>, true, Record<string, never>, undefined>; } & {
    readonly schema: UnionToTuple<{ readonly [Property in keyof TEnum]: TreeNodeSchemaClass<ScopedSchemaName<TScope, TEnum[Property]>, NodeKind.Object, TreeNode & {
        readonly value: TEnum[Property];
    }, Record<string, never>, true, Record<string, never>, undefined>; }[keyof TEnum]>;
};
/**
 * Returns en "entries" (like Object.entries) for an enum object, omitting the
 * {@link https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings|reverse mappings}
 */
export declare function enumEntries(enumObject: Record<string, string | number>): [string, string | number][];
/**
 * Converts an array of distinct strings into a collection of schema which can be used like an enum style union.
 * @remarks
 * The returned collection is also a function which can be used to convert strings into {@link Unhydrated} nodes in the union.
 * Each node type has a `.value` getter which returns the associated string.
 *
 * The produced nodes use the provided strings as their `name`, and don't store any data beyond that.
 * @example
 * ```typescript
 * const schemaFactory = new SchemaFactory("com.myApp");
 * const Mode = enumFromStrings(schemaFactory, ["Fun", "Cool"]);
 * type Mode = TreeNodeFromImplicitAllowedTypes<typeof Mode.schema>;
 * const nodeFromString: Mode = Mode("Fun");
 * const nodeFromSchema: Mode = new Mode.Fun();
 *
 * // Schema nodes have a strongly typed `.value` property.
 * const nameFromNode: "Fun" | "Cool" = nodeFromSchema.value;
 *
 * class Parent extends schemaFactory.object("Parent", { mode: Mode.schema }) {}
 * ```
 * @see {@link adaptEnum} for a similar function that works on enums instead of arrays of strings.
 * @beta
 */
export declare function enumFromStrings<TScope extends string, const Members extends readonly string[]>(factory: SchemaFactory<TScope>, members: Members): (<TValue extends Members[number]>(value: TValue) => TValue extends unknown ? TreeNode & {
    readonly value: TValue;
} : never) & { [Index in Extract<keyof Members, `${number}`> extends `${infer N extends number}` ? N : never as Members[Index]]: TreeNodeSchemaClass<ScopedSchemaName<TScope, Members[Index]>, NodeKind.Object, TreeNode & {
    readonly value: Members[Index];
}, Record<string, never>, true, Record<string, never>, undefined>; } & {
    readonly schema: UnionToTuple<Members[number] extends unknown ? { [Index in Extract<keyof Members, `${number}`> extends `${infer N extends number}` ? N : never as Members[Index]]: TreeNodeSchemaClass<ScopedSchemaName<TScope, Members[Index]>, NodeKind.Object, TreeNode & {
        readonly value: Members[Index];
    }, Record<string, never>, true, Record<string, never>, undefined>; }[Members[number]] : never>;
};
/**
 * Declare a SchemaFactory for use in cases where the Fluid Framework's code creates the schema and owns its schema compatibility (and thus scope)
 * but it is parameterized by user provided data, the `TUserScope`.
 * @remarks
 * This should allow future logic in {@link generateSchemaFromSimpleSchema} to recognize these schema as ones defined by Fluid Framework,
 * and special case them to provide better APIs and maintain data invariants.
 */
export declare function createCustomizedFluidFrameworkScopedFactory<TUserScope extends string, TCreatorDomain extends string>(inputSchemaFactory: SchemaFactoryBeta<TUserScope>, fluidDomainSuffix: TCreatorDomain): SchemaFactoryBeta<`com.fluidframework.${TCreatorDomain}<${TUserScope}>`>;
//# sourceMappingURL=schemaCreationUtilities.d.ts.map