import { ValueType, TypeAnalyzer, CollectedTypes } from '@previewjs/type-analyzer';
import { Reader } from '@previewjs/vfs';
import * as express from 'express';
import express__default from 'express';
import * as vite from 'vite';
import vite__default from 'vite';
import { Endpoint, RequestOf, ResponseOf, localEndpoints } from '@previewjs/api';
import { PreviewConfig } from '@previewjs/config';
import ts from 'typescript';

declare type RegisterEndpoint = <E extends Endpoint<any, any>>(endpoint: E, handler: RequestHandler<RequestOf<E>, ResponseOf<E>>) => void;
declare type RequestHandler<Req, Res> = (request: Req, expressRequest: express.Request, expressResponse: express.Response) => Promise<Res>;
declare type RequestHandlerForEndpoint<E> = E extends Endpoint<infer Req, infer Res> ? RequestHandler<Req, Res> : never;

interface PersistedStateManager {
    get: RequestHandlerForEndpoint<typeof localEndpoints.GetState>;
    update: RequestHandlerForEndpoint<typeof localEndpoints.UpdateState>;
}

declare type PackageDependencies = Record<string, {
    /** @deprecated */
    majorVersion: number;
    readInstalledVersion(): Promise<string | null>;
}>;

interface FrameworkPluginFactory {
    isCompatible(dependencies: PackageDependencies): Promise<boolean>;
    create(): Promise<FrameworkPlugin>;
}
interface FrameworkPlugin {
    readonly pluginApiVersion?: number;
    readonly name: string;
    readonly defaultWrapperPath: string;
    readonly previewDirPath: string;
    readonly transformReader?: (reader: Reader, rootDirPath: string) => Reader;
    readonly tsCompilerOptions?: Partial<ts.CompilerOptions>;
    readonly specialTypes?: Record<string, ValueType>;
    readonly viteConfig: (config: PreviewConfig) => vite__default.UserConfig;
    readonly incompatibleVitePlugins?: string[];
    readonly detectComponents: (typeAnalyzer: TypeAnalyzer, absoluteFilePaths: string[]) => Promise<Component[]>;
}
interface Component {
    readonly absoluteFilePath: string;
    readonly name: string;
    readonly offsets: Array<[start: number, end: number]>;
    readonly info: {
        kind: "component";
        readonly exported: boolean;
        readonly analyze: () => Promise<ComponentAnalysis>;
    } | {
        kind: "story";
        readonly associatedComponent: {
            readonly absoluteFilePath: string;
            readonly name: string;
        } | null;
    };
}
interface ComponentAnalysis {
    propsType: ValueType;
    types: CollectedTypes;
}

declare function generateComponentId(options: {
    currentFilePath: string;
    siblingFileName?: string;
    name: string;
}): string;

declare type SetupPreviewEnvironment = (options: {
    rootDirPath: string;
}) => Promise<PreviewEnvironment>;
declare type PreviewEnvironment = {
    middlewares?: express.RequestHandler[];
    persistedStateManager?: PersistedStateManager;
    onReady?(options: {
        registerEndpoint: RegisterEndpoint;
        workspace: Workspace;
    }): Promise<void>;
};
declare function loadPreviewEnv({ rootDirPath, setupEnvironment, frameworkPluginFactories, }: {
    rootDirPath: string;
    setupEnvironment: SetupPreviewEnvironment;
    frameworkPluginFactories?: FrameworkPluginFactory[];
}): Promise<{
    previewEnv: PreviewEnvironment;
    frameworkPlugin: FrameworkPlugin;
} | null>;

declare function createWorkspace({ versionCode, rootDirPath, reader, frameworkPlugin, logLevel, middlewares, onReady, persistedStateManager, }: {
    versionCode: string;
    rootDirPath: string;
    middlewares: express__default.RequestHandler[];
    frameworkPlugin: FrameworkPlugin;
    logLevel: vite.LogLevel;
    reader: Reader;
    persistedStateManager?: PersistedStateManager;
    onReady?(options: {
        registerEndpoint: RegisterEndpoint;
        workspace: Workspace;
    }): Promise<void>;
}): Promise<Workspace>;
/**
 * Returns the absolute directory path of the closest ancestor containing node_modules.
 */
declare function findWorkspaceRoot(absoluteFilePath: string): string | null;
interface Workspace {
    rootDirPath: string;
    reader: Reader;
    typeAnalyzer: TypeAnalyzer;
    frameworkPlugin: FrameworkPlugin;
    preview: {
        start(allocatePort?: () => Promise<number>): Promise<Preview>;
    };
    dispose(): Promise<void>;
}
interface Preview {
    url(): string;
    stop(options?: {
        onceUnused?: boolean;
    }): Promise<void>;
}

export { Component, ComponentAnalysis, FrameworkPlugin, FrameworkPluginFactory, PersistedStateManager, Preview, PreviewEnvironment, SetupPreviewEnvironment, Workspace, createWorkspace, findWorkspaceRoot, generateComponentId, loadPreviewEnv };
