import type { CustomDirective, StreamRenderer, StxOptions } from './types';
/**
 * Stream a template with data using chunked transfer encoding.
 *
 * This implements actual progressive streaming by:
 * 1. Sending the shell (content before suspense) immediately
 * 2. Processing suspense boundaries in parallel
 * 3. Streaming each resolved suspense content as it completes
 * 4. Using out-of-order streaming with client-side reordering
 *
 * @param templatePath Path to the template
 * @param data Data to render with the template
 * @param options stx options
 */
export declare function streamTemplate(templatePath: string, data?: Record<string, any>, options?: StxOptions): Promise<ReadableStream<string>>;
/**
 * Build the <script> chunk that resolves a single suspense boundary.
 *
 * On success it injects the rendered content (backtick- and
 * </script>-escaped so it can't break out of the template literal). On
 * rejection it injects a marked-up, HTML-escaped error UI instead of
 * letting the failure take down the whole stream — one boundary's error
 * is isolated to that boundary's placeholder.
 *
 * Extracted from the inline resolve loop so the error path is directly
 * unit-testable with a rejecting promise, without mocking the render
 * pipeline (the previous test mocked `processDirectives` via
 * `mock.module`, which is process-global in Bun and leaked into every
 * later test in the run — the root cause of a large cross-contamination
 * cluster). See stacksjs/stx#1711.
 */
export declare function buildSuspenseResolveScript(name: string, promise: Promise<string>): Promise<string>;
export declare function renderStreamingPage(shellHtml: string, boundaries?: StreamBoundary[], options?: RenderStreamingOptions): ReadableStream<string>;
/**
 * Declarative streaming-SSR sugar (#1746 Phase 3). Extracts each
 * `@stream('id') <content> @fallback <fallback> @endstream` block, stashes the
 * RAW inner template on `context.__streamTemplates[id]` (re-rendered later with
 * `$boundary` data, so its `{{ }}` / directives stay un-evaluated now), and
 * replaces the block with the fallback inside a `data-suspense="id"` placeholder
 * — which flows through the normal pipeline. Distinct from the client-side
 * `@suspense` directive (suspense.ts), so the two don't collide.
 *
 * Runs early (before loops/expressions) so the captured template is pristine.
 */
export declare function processStreamDirectives(template: string, context: Record<string, any>): string;
/**
 * Read streaming-SSR boundaries off a rendered page's server context (#1746
 * Phase 3). A page opts in by exporting `streamBoundaries` from `<script
 * server>` — a map of boundary id → server-side async render. Returns the
 * boundary list (sorted-stable by declaration), or `undefined` when the page
 * declared none. Non-function entries are ignored.
 */
export declare function extractStreamBoundaries(context: Record<string, unknown> | undefined | null): StreamBoundary[] | undefined;
/**
 * Stream a template with data (simple version without suspense).
 * Returns full content in chunks based on buffer size.
 *
 * @param templatePath Path to the template
 * @param data Data to render with the template
 * @param options stx options
 */
export declare function streamTemplateSimple(templatePath: string, data?: Record<string, any>, options?: StxOptions): Promise<ReadableStream<string>>;
/**
 * Create a stream renderer for progressive loading
 * @param templatePath Path to the template
 * @param options stx options
 */
export declare function createStreamRenderer(templatePath: string, options?: StxOptions): Promise<StreamRenderer>;
/**
 * Register streaming and hydration directives
 */
export declare function registerStreamingDirectives(options?: StxOptions): CustomDirective[];
/**
 * Process section directives
 * @param content Template content
 * @param context Data context
 * @param filePath Template file path
 * @param _options stx options
 */
// eslint-disable-next-line pickier/no-unused-vars
export declare function processSectionDirectives(content: string, context: Record<string, any>, filePath: string, _options?: StxOptions): Promise<string>;
/**
 * Wrap a ReadableStream<string> in a proper Response with chunked transfer encoding headers.
 *
 * Makes it trivial to use streaming from a Bun server handler:
 *
 * @example
 * ```typescript
 * const server = Bun.serve({
 *   async fetch(req) {
 *     const stream = await streamTemplate('index.stx', { title: 'Home' })
 *     return streamToResponse(stream)
 *   }
 * })
 * ```
 *
 * @param stream - The template ReadableStream
 * @param init - Optional additional ResponseInit (headers, status, etc.)
 * @returns A Response with proper streaming headers
 */
export declare function streamToResponse(stream: ReadableStream<string>, init?: ResponseInit): Response;
/**
 * Generate client-side hydration runtime script.
 *
 * This script handles:
 * - Finding islands in the DOM
 * - Loading island components based on priority
 * - Hydrating islands with their props
 *
 * Usage: Include the generated script in your page, then call
 * `window.__stx.hydrate()` when ready.
 *
 * @example
 * ```html
 * <script>
 *   {{ generateHydrationRuntime({ mode: 'full' }) }}
 * </script>
 * ```
 */
export declare function generateHydrationRuntime(config?: HydrationRuntimeConfig): string;
/**
 * Client receiver for streamed boundaries. Emitted once, right after the shell:
 * defines `window.__stxSuspense.resolve(id, html)`, which swaps the boundary's
 * fallback placeholder (`[data-suspense="id"]`) for the streamed content.
 * Idempotent (`|| { … }`) so multiple streamed renders on one document — or a
 * re-run after SPA nav — don't clobber an in-flight receiver.
 */
export declare const SUSPENSE_RESOLVER_RUNTIME: string;
/**
 * Custom directive for marking suspense boundaries in streaming templates.
 *
 * Usage:
 * ```html
 * @suspense('heavy-content')
 *   <div>This content will stream after the shell</div>
 * @endsuspense
 * ```
 *
 * The content inside suspense boundaries will be:
 * 1. Replaced with a placeholder in the initial shell
 * 2. Processed in parallel with other suspense boundaries
 * 3. Streamed to the client as it resolves
 * 4. Injected into the placeholder via client-side JavaScript
 */
export declare const streamingSuspenseDirective: CustomDirective;
/**
 * Custom directive for creating islands (for partial hydration)
 */
export declare const islandDirective: CustomDirective;
/** A deferred streaming boundary: its `render` does the server-side async work. */
export declare interface StreamBoundary {
  id: string
  render: () => Promise<string>
}
/**
 * Render a streaming-SSR page (#1746 Phase 3). Flushes the shell — which carries
 * each boundary's fallback in a `[data-suspense="<id>"]` placeholder — to the
 * browser immediately, then streams each boundary's HTML as its server-side
 * async `render()` resolves, in completion order. The browser paints the shell
 * at once and each slow region swaps in when its data is ready.
 *
 * Per-boundary errors are isolated (`buildSuspenseResolveScript` emits an error
 * UI into that boundary instead of failing the whole stream). Pair with
 * `streamToResponse` to get a chunked HTTP `Response`.
 */
export declare interface RenderStreamingOptions {
  timeoutMs?: number
}
/**
 * Configuration for hydration runtime generation
 */
export declare interface HydrationRuntimeConfig {
  mode: 'full' | 'loader'
  components?: Record<string, string>
  dynamicImports?: boolean
}
