import { type Maybe } from '@takeshape/util';
import type { Args, ObjectSchema, ProjectSchemaJSON, PropertySchema, QueryJSON, Ref, ReturnShape, ShapeJSON, ShapeSchema, ToolJSON } from './project-schema/index.ts';
import { type LayerSchema, type SchemaPath } from './types/index.ts';
export type ServicesContext = Pick<ProjectSchemaJSON, 'services'>;
export type ServicesShapesContext = Pick<ProjectSchemaJSON, 'services' | 'shapes'>;
export declare const LOCAL_LAYER_ID = "local";
/**
 * This interface describes a parsed `@ref` or `$ref`.
 * The intended usage is to convert a schema with a ref to a RefItem which can then
 * be passed to the various rich utilities in this file.
 */
export type RefItem = {
    shapeName: string;
    layerId: string;
    template?: string;
};
export type PropertyRefItem = RefItem & {
    propertyName: string;
};
/**
 * Adds a schema path, needed when visiting a whole schema to report errors.
 */
export type RefItemWithPath = {
    path: SchemaPath;
} & RefItem;
/**
 * Parse a template like `PaginatedList<Post>` and return both the template and the shape name.
 */
export declare function parseTemplateShape(shapeExpression: string): {
    template: string | undefined;
    shapeName: string;
};
export type ParsedReturnShape = {
    isArray: boolean;
    template?: string;
    shapeName: string;
    ref?: RefItem;
};
export declare function parseReturnShape(context: ServicesContext, shape: ReturnShape): ParsedReturnShape;
/**
 * Convert Query.shape to a PropertySchema
 */
export declare function returnShapeToSchema(projectSchema: ServicesContext, returnShape: ReturnShape): PropertySchema;
/**
 * Create a template string like `PaginatedList<Post>` from a template and shape name.
 */
export declare function createTemplateShapeName(template: string, shapeName: string): string;
/**
 * If the string is a template like `PaginatedList<Post>`, return the shape name,
 * in this case `Post`. Otherwise return the input.
 */
export declare const untemplate: (input: string) => string;
export declare function getFlattenedTemplateShapeName(shapeName: string, template?: string): string;
export declare function refSchemaToPath(context: ServicesContext, refSchema: PropertySchema): string[];
/**
 * Safely turn a "template" shape reference (`@args`, `args`, `shape`) into a `RefItem`
 *
 * @param context A partial project schema
 * @param refExpression
 * A ref expression might include "template" name and refer to a local or remote
 * shape, `Foo` or `CreateArgs<Foo>` or `CreateArgs<remote:Foo>`.*
 */
export declare function parseRef(context: ServicesContext, refExpression: string): RefItem;
export declare function isRefEqual(context: ServicesContext, a: string | RefItem, b: string | RefItem): boolean;
/**
 * Converts a list of ref expressions into a list of ref items.
 */
export declare function refExpressionListToRefItemList(context: ServicesContext, refExpressionList: Ref[]): RefItem[];
/**
 * Sugar for converting a `refExpression` directly into a shape, without the
 * intermediate `refItem`.
 *
 * @param context A partial project schema
 * @param refExpression
 * A ref expression might include "template" name and refer to a local or remote
 * shape, `Foo` or `CreateArgs<Foo>` or `CreateArgs<remote:Foo>`.
 */
export declare function getShapeByRef(context: ServicesShapesContext, refExpression: string): Maybe<ShapeJSON>;
export declare function isValidServiceId(context: ServicesContext, serviceId: string): boolean;
export declare function isValidRefItem(context: ServicesContext): (refItem: RefItem) => boolean;
export declare function refToRefItem(context: ServicesContext, $ref: string, template?: string): RefItem;
export type ParsedName = {
    layerId: string;
    name: string;
};
/**
 * Parse a name (query, shape, etc) that might have a namespace and find the corresponding service layer id
 */
export declare function parseName(context: ServicesContext, name: string): ParsedName;
export declare function shapeToRefItem(context: ServicesContext, shape: ShapeJSON): RefItem;
export declare function shapeToRefString(context: ServicesContext, shape: ShapeJSON): string;
/**
 * Given a property schema and project schema, finds a `@ref` or `$ref` and
 * returns a `RefItem` suitable for loading a referenced schema...
 */
export declare function getRef(context: ServicesContext, refSchema: PropertySchema): Maybe<RefItem>;
export declare function getRefWithPath(context: ServicesContext, refSchema: PropertySchema, schemaPath?: SchemaPath): Maybe<RefItemWithPath>;
/**
 * Tests for a `@ref` or `$ref` property directly on the passed schema.
 *
 * @param schema Any schema that might could have a ref property.
 */
export declare function hasRefProperty(schema: PropertySchema): boolean;
/**
 * From a property that has oneOf or items with oneOf, get all refs
 */
export declare function getOneOfRefs(context: ServicesContext, propertySchema: PropertySchema, schemaPath?: SchemaPath): RefItemWithPath[];
/**
 * From a schema with a ref, will return the top-level ref, and potentially
 * a ref item from a nested `items` property.
 */
export declare function getRefOrItemsRef(context: ServicesContext, refSchema: PropertySchema, schemaPath?: SchemaPath): Maybe<RefItemWithPath>;
/**
 * Turns a `RefItem` into an `@ref`.
 */
export declare function serializeRef(refItem: RefItem): string;
/**
 * Turns a `RefItem` into a standard shape name, namespacing if present.
 */
export declare function refItemToNamespacedShapeName(context: ServicesContext, refItem: RefItem): string;
export declare function refExpressionToNamespacedName(context: ServicesContext, refExpression: string): string;
/**
 * Turns a `RefItem` into a path suitable for `lodash.get`.
 */
export declare function refItemToShapePath(context: ServicesContext, refItem: RefItem): string[];
/**
 * Get a Shape referenced by a `RefItem`.
 */
export declare function refItemToShape(context: ServicesShapesContext, refItem: RefItem): Maybe<ShapeJSON>;
/**
 * Get all shapes referenced by a RefItem array.
 */
export declare function refItemListToShapeList(context: ServicesShapesContext, refItems: RefItem[]): ShapeJSON[];
/**
 * Get a shape referenced by a `RefItem`, also returning the path to the new shape.
 */
export declare function refItemToShapeWithPath(context: ServicesShapesContext, refItem: RefItem): Maybe<{
    shape: ShapeJSON;
    path: string[];
}>;
/**
 * Get a Shape schema referenced by a `RefItem`.
 */
export declare function refItemToShapeSchema(context: ServicesShapesContext, refItem: RefItem): Maybe<ShapeSchema>;
/**
 * Sugar, for when you really just need a string...
 */
export declare function getRefShapeName(context: ServicesContext, refSchema: PropertySchema): Maybe<string>;
/**
 * Sugar, for when you really just need a path...
 */
export declare function refSchemaToShapeSchemaPath(context: ServicesContext, refSchema: PropertySchema): Maybe<string[]>;
/**
 * Helper fn to omit `ref` props from the target schema, and then extend it with the source schema.
 */
export declare const omitRefAndExtend: (targetSchema: PropertySchema, sourceSchema: PropertySchema) => import("lodash").Omit<PropertySchema, "@ref" | "$ref"> & PropertySchema;
/**
 * If there is a $ref, this will insert a property schema from the top level
 * in place of the reference.
 */
export declare function followRef(context: ServicesShapesContext, schema: PropertySchema, ref?: RefItem): PropertySchema;
/**
 * Returns whether a schema has refs.
 */
export declare function hasRef(schema: PropertySchema): boolean;
/**
 * Returns whether a schema has refs which can be followed.
 */
export declare function hasResolvableRef(context: ServicesShapesContext, schema: PropertySchema): boolean;
/**
 * Given a schema, will resolve any `allOf` or `ref` objects. This function has
 * to fully resolve all refs, because attempting to extend an object schema with
 * a ref property would create an invalid schema, potentially containing both
 * a ref and properties.
 *
 * If it can't create a valid schema it returns the input.
 */
export declare function dereferenceSchema(context: ServicesShapesContext, shapeOrFieldSchema: PropertySchema, schemaPath?: SchemaPath): PropertySchema;
export declare function dereferenceObjectSchema(context: ServicesShapesContext, shapeOrFieldSchema: PropertySchema, schemaPath?: SchemaPath): ObjectSchema;
export type GetNamespace = (layerId: string) => Maybe<string>;
export declare function createGetNamespace(context: ServicesContext): GetNamespace;
export declare function parsePropertyRef(refStr: string, defaultShape?: string): Maybe<PropertyRefItem>;
export declare function serializePropertyRef({ shapeName, propertyName, layerId }: PropertyRefItem): string;
export declare function normalizePropertyRef(refStr: string, defaultShape?: string): string;
export declare function propertyRefToShapeRef(propertyRef: string): string | undefined;
export declare function mappingToShapeRefs(prop: Pick<PropertySchema, '@mapping'>): string[];
export declare function formatShapeRef(layerId: string, shapeName: string): string;
export declare function applyNamespace(namespace: string | undefined, name: string): string;
export declare function propertyRefItemToResolverPath(getNamespace: GetNamespace, item: PropertyRefItem): string[];
export declare function propertyRefItemToArgsPath(getNamespace: GetNamespace, item: PropertyRefItem): string[];
export declare function propertyRefItemToPath(getNamespace: GetNamespace, item: PropertyRefItem): string[];
export declare function resolvePropertyRef(schema: ProjectSchemaJSON | LayerSchema, item: PropertyRefItem): PropertySchema | QueryJSON | ToolJSON | undefined;
export declare function propertyRefToArgs(projectSchema: ProjectSchemaJSON, ref: string | PropertyRefItem): Maybe<Args>;
/**
 * Get a ref to the given shape.
 */
export declare function normalizeRefExpression(context: ServicesContext, refExpression: string): string;
export declare function normalizeLocalRefString(ref: string): string;
export declare function getAllPropertyRefs(projectSchema: ProjectSchemaJSON): PropertyRefItem[];
export type QueryEntry = {
    name: string;
    query: QueryJSON;
    ref: PropertyRefItem;
};
export declare function getQuery(projectSchema: Pick<ProjectSchemaJSON, 'services' | 'shapes' | 'queries' | 'mutations'>, queryRef: string): Maybe<QueryEntry>;
export declare function ensureQuery(projectSchema: ProjectSchemaJSON, queryRef: string): QueryEntry;
export declare function normalizeRefs(projectSchema: ProjectSchemaJSON): ProjectSchemaJSON;
export declare function normalizeRefs(projectSchema: ProjectSchemaJSON, property?: PropertySchema): PropertySchema;
/**
 * Get a ShapeJSON from a RefItem, with the schema dereferenced.
 */
export declare function getReferencedShape(projectSchema: ProjectSchemaJSON, refItem: PropertyRefItem, namespace?: string): (ShapeJSON & {
    schema: PropertySchema;
}) | undefined;
/**
 * Get a PropertySchema from a RefItem.
 */
export declare function getReferencedShapeProperty(projectSchema: ProjectSchemaJSON, refItem: PropertyRefItem, namespace?: string): PropertySchema | undefined;
export declare function getToolQueryRef({ execution }: Pick<ToolJSON, 'execution'>): string | undefined;
export declare function getToolRef(tool: Pick<ToolJSON, 'execution'>): string | undefined;
