{"version":3,"file":"streaming-middleware.mjs","sources":["../../../../src/lib/streaming/server/streaming-middleware.ts"],"sourcesContent":["/**\n * @file Streaming Middleware Utilities\n * @description Server-side utilities for SSR streaming integration.\n *\n * This module provides middleware patterns, utilities, and helpers for\n * integrating the Dynamic HTML Streaming Engine with server-side rendering\n * frameworks like Express, Fastify, or Next.js.\n *\n * @module streaming/server/streaming-middleware\n * @version 1.0.0\n * @author Harbor Framework Team\n *\n * @example\n * ```typescript\n * // Express integration\n * import { createStreamingMiddleware } from '@/lib/streaming/server';\n *\n * app.use(createStreamingMiddleware({\n *   compress: true,\n *   enableEarlyHints: true,\n * }));\n *\n * app.get('/', async (req, res) => {\n *   const stream = await renderToStreamingResponse(App, req);\n *   stream.pipe(res);\n * });\n * ```\n */\n\nimport type {\n  StreamingMiddlewareOptions,\n  ServerStreamContext,\n  SerializedStreamState,\n  StreamConfig,\n  StreamChunk,\n} from '../types';\nimport { StreamState, StreamPriority, calculateChecksum } from '../streaming-engine';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Default middleware options.\n */\nconst DEFAULT_MIDDLEWARE_OPTIONS: Required<StreamingMiddlewareOptions> = {\n  compress: true,\n  compressThreshold: 1024,\n  headers: {},\n  nonceGenerator: () => generateNonce(),\n  timeoutMs: 30000,\n  enableEarlyHints: false,\n  onError: () => {},\n};\n\n/**\n * Streaming-specific HTTP headers.\n */\nconst STREAMING_HEADERS = {\n  CONTENT_TYPE: 'Content-Type',\n  TRANSFER_ENCODING: 'Transfer-Encoding',\n  X_ACCEL_BUFFERING: 'X-Accel-Buffering',\n  CACHE_CONTROL: 'Cache-Control',\n  X_STREAM_BOUNDARY: 'X-Stream-Boundary',\n  X_STREAM_NONCE: 'X-Stream-Nonce',\n} as const;\n\n// ============================================================================\n// Nonce Generation\n// ============================================================================\n\n/**\n * Generates a cryptographically secure nonce for CSP.\n *\n * @returns Base64-encoded nonce string\n *\n * @example\n * ```typescript\n * const nonce = generateNonce();\n * // Returns: \"abc123def456...\"\n * ```\n */\nexport function generateNonce(): string {\n  if (typeof crypto !== 'undefined' && crypto !== null && typeof crypto.randomUUID === 'function') {\n    return crypto.randomUUID().replace(/-/g, '');\n  }\n\n  // Fallback for older environments\n  const array = new Uint8Array(16);\n  if (\n    typeof crypto !== 'undefined' &&\n    crypto !== null &&\n    typeof crypto.getRandomValues === 'function'\n  ) {\n    crypto.getRandomValues(array);\n  } else {\n    // Last resort fallback\n    for (let i = 0; i < 16; i++) {\n      array[i] = Math.floor(Math.random() * 256);\n    }\n  }\n\n  return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n// ============================================================================\n// Stream Context Factory\n// ============================================================================\n\n/**\n * Creates a server stream context for managing streaming output.\n *\n * @description\n * The server stream context provides a consistent interface for writing\n * streaming content regardless of the underlying HTTP server framework.\n *\n * @param writer - The write function for the response\n * @param flush - Optional flush function\n * @param options - Middleware options\n * @returns Server stream context\n *\n * @example\n * ```typescript\n * const context = createServerStreamContext(\n *   (chunk) => res.write(chunk),\n *   () => res.flush?.(),\n *   { nonce: 'abc123' }\n * );\n *\n * context.write('<div>Content</div>');\n * context.flush();\n * context.end();\n * ```\n */\nexport function createServerStreamContext(\n  writer: (chunk: string | Uint8Array) => void,\n  flush?: () => void,\n  options: Partial<StreamingMiddlewareOptions> = {}\n): ServerStreamContext {\n  const mergedOptions = { ...DEFAULT_MIDDLEWARE_OPTIONS, ...options };\n  const requestId = generateNonce().slice(0, 8);\n  const nonce = mergedOptions.nonceGenerator();\n  const headers = new Map<string, string>();\n\n  // Set default streaming headers\n  headers.set(STREAMING_HEADERS.CONTENT_TYPE, 'text/html; charset=utf-8');\n  headers.set(STREAMING_HEADERS.TRANSFER_ENCODING, 'chunked');\n  headers.set(STREAMING_HEADERS.X_ACCEL_BUFFERING, 'no'); // Disable nginx buffering\n  headers.set(STREAMING_HEADERS.X_STREAM_NONCE, nonce);\n\n  // Add custom headers\n  for (const [key, value] of Object.entries(mergedOptions.headers)) {\n    headers.set(key, value);\n  }\n\n  return {\n    write: (chunk: string | Uint8Array) => {\n      try {\n        writer(chunk);\n      } catch (error) {\n        mergedOptions.onError?.(error as Error);\n      }\n    },\n    flush: () => {\n      try {\n        flush?.();\n      } catch (error) {\n        mergedOptions.onError?.(error as Error);\n      }\n    },\n    end: () => {\n      // Signal end of stream - implementation depends on framework\n    },\n    nonce,\n    requestId,\n    headers,\n  };\n}\n\n// ============================================================================\n// Streaming Response Helpers\n// ============================================================================\n\n/**\n * Creates streaming response headers.\n *\n * @param options - Middleware options\n * @returns Headers object for streaming response\n */\nexport function createStreamingHeaders(\n  options: Partial<StreamingMiddlewareOptions> = {}\n): Record<string, string> {\n  const mergedOptions = { ...DEFAULT_MIDDLEWARE_OPTIONS, ...options };\n  const nonce = mergedOptions.nonceGenerator();\n\n  const headers: Record<string, string> = {\n    [STREAMING_HEADERS.CONTENT_TYPE]: 'text/html; charset=utf-8',\n    [STREAMING_HEADERS.TRANSFER_ENCODING]: 'chunked',\n    [STREAMING_HEADERS.X_ACCEL_BUFFERING]: 'no',\n    [STREAMING_HEADERS.X_STREAM_NONCE]: nonce,\n    ...mergedOptions.headers,\n  };\n\n  if (!mergedOptions.compress) {\n    headers['Content-Encoding'] = 'identity';\n  }\n\n  return headers;\n}\n\n/**\n * Creates early hints (103) headers for resource preloading.\n *\n * @param resources - Resources to preload\n * @returns Early hints headers\n *\n * @example\n * ```typescript\n * const hints = createEarlyHints([\n *   { href: '/styles.css', as: 'style' },\n *   { href: '/app.js', as: 'script' },\n * ]);\n * ```\n */\nexport interface PreloadResource {\n  href: string;\n  as: 'script' | 'style' | 'font' | 'image' | 'fetch';\n  crossOrigin?: 'anonymous' | 'use-credentials';\n  type?: string;\n}\n\nexport function createEarlyHints(resources: PreloadResource[]): string[] {\n  return resources.map((resource) => {\n    let hint = `<${resource.href}>; rel=preload; as=${resource.as}`;\n    if (resource.crossOrigin != null) {\n      hint += `; crossorigin=${resource.crossOrigin}`;\n    }\n    if (resource.type != null && resource.type !== '') {\n      hint += `; type=${resource.type}`;\n    }\n    return hint;\n  });\n}\n\n// ============================================================================\n// Stream Serialization\n// ============================================================================\n\n/**\n * Serializes stream state for client-side hydration.\n *\n * @description\n * Creates a serialized representation of stream state that can be\n * embedded in the HTML for client-side rehydration.\n *\n * @param boundaryId - Boundary identifier\n * @param content - Rendered content\n * @param metadata - Additional metadata\n * @returns Serialized stream state\n *\n * @example\n * ```typescript\n * const serialized = serializeStreamState('hero', '<div>Hero Content</div>');\n * // Embed in HTML for hydration\n * ```\n */\nexport function serializeStreamState(\n  boundaryId: string,\n  content: string,\n  metadata?: Record<string, unknown>\n): SerializedStreamState {\n  return {\n    boundaryId,\n    state: StreamState.Completed,\n    content,\n    checksum: calculateChecksum(content),\n    serverTimestamp: Date.now(),\n    metadata,\n  };\n}\n\n/**\n * Creates a script tag for hydrating stream state on the client.\n *\n * @param states - Array of serialized stream states\n * @param nonce - CSP nonce\n * @returns HTML script tag string\n */\nexport function createHydrationScript(states: SerializedStreamState[], nonce?: string): string {\n  const data = JSON.stringify(states);\n  const nonceAttr = nonce != null && nonce !== '' ? ` nonce=\"${nonce}\"` : '';\n\n  return `<script${nonceAttr}>\n    window.__STREAM_STATE__ = window.__STREAM_STATE__ || [];\n    window.__STREAM_STATE__.push(...${data});\n  </script>`;\n}\n\n/**\n * Deserializes stream state from hydration data.\n *\n * @param data - Serialized state data\n * @returns Parsed stream state or null if invalid\n */\nexport function deserializeStreamState(data: unknown): SerializedStreamState | null {\n  if (data == null || typeof data !== 'object') return null;\n\n  const state = data as Partial<SerializedStreamState>;\n\n  if (\n    typeof state.boundaryId !== 'string' ||\n    typeof state.content !== 'string' ||\n    typeof state.checksum !== 'string'\n  ) {\n    return null;\n  }\n\n  // Verify checksum\n  const computedChecksum = calculateChecksum(state.content);\n  if (computedChecksum !== state.checksum) {\n    console.warn(`[StreamHydration] Checksum mismatch for boundary \"${state.boundaryId}\"`);\n    return null;\n  }\n\n  return state as SerializedStreamState;\n}\n\n// ============================================================================\n// Stream Boundary Markers\n// ============================================================================\n\n/**\n * Creates HTML markers for stream boundaries.\n *\n * @description\n * These markers are used to identify stream boundary locations in the\n * HTML output, enabling client-side hydration and activation.\n */\nexport const StreamMarkers = {\n  /**\n   * Creates a start marker for a stream boundary.\n   */\n  start: (boundaryId: string, config?: Partial<StreamConfig>): string => {\n    const attrs = config\n      ? ` data-priority=\"${config.priority ?? 'normal'}\" data-defer=\"${config.deferMs ?? 0}\"`\n      : '';\n    return `<!--stream:start:${boundaryId}${attrs}-->`;\n  },\n\n  /**\n   * Creates an end marker for a stream boundary.\n   */\n  end: (boundaryId: string): string => {\n    return `<!--stream:end:${boundaryId}-->`;\n  },\n\n  /**\n   * Creates a placeholder marker.\n   */\n  placeholder: (boundaryId: string): string => {\n    return `<div data-stream-placeholder=\"${boundaryId}\" style=\"display:contents\"></div>`;\n  },\n\n  /**\n   * Creates an error marker.\n   */\n  error: (boundaryId: string, message: string): string => {\n    const escaped = message.replace(/--/g, '- -');\n    return `<!--stream:error:${boundaryId}:${escaped}-->`;\n  },\n};\n\n// ============================================================================\n// Chunk Creation Utilities\n// ============================================================================\n\n/**\n * Creates a stream chunk for server-side streaming.\n *\n * @param data - Chunk data\n * @param boundaryId - Parent boundary ID\n * @param sequence - Chunk sequence number\n * @param isFinal - Whether this is the final chunk\n * @returns Stream chunk\n */\nexport function createServerChunk(\n  data: string,\n  boundaryId: string,\n  sequence: number,\n  isFinal = false\n): StreamChunk {\n  return {\n    id: `${boundaryId}-chunk-${sequence}`,\n    sequence,\n    data,\n    timestamp: Date.now(),\n    size: new TextEncoder().encode(data).length,\n    isFinal,\n    boundaryId,\n    checksum: calculateChecksum(data),\n  };\n}\n\n/**\n * Wraps content in stream boundary markers with activation script.\n *\n * @param boundaryId - Boundary identifier\n * @param content - Content to wrap\n * @param nonce - CSP nonce\n * @param config - Stream configuration\n * @returns Wrapped content string\n */\nexport function wrapBoundaryContent(\n  boundaryId: string,\n  content: string,\n  nonce?: string,\n  config?: Partial<StreamConfig>\n): string {\n  const nonceAttr = nonce != null && nonce !== '' ? ` nonce=\"${nonce}\"` : '';\n  const priority = config?.priority ?? StreamPriority.Normal;\n\n  return `\n${StreamMarkers.start(boundaryId, config)}\n<div data-stream-id=\"${boundaryId}\" data-stream-state=\"completed\" data-stream-priority=\"${priority}\">\n${content}\n</div>\n<script${nonceAttr}>\n(function() {\n  if (window.__STREAM_BOUNDARIES__) {\n    window.__STREAM_BOUNDARIES__.complete('${boundaryId}');\n  }\n})();\n</script>\n${StreamMarkers.end(boundaryId)}\n`.trim();\n}\n\n// ============================================================================\n// Streaming Pipeline Utilities\n// ============================================================================\n\n/**\n * Creates a priority-sorted stream pipeline.\n *\n * @description\n * Organizes stream boundaries by priority for optimal streaming order.\n *\n * @param boundaries - Map of boundary configurations\n * @returns Sorted array of boundary entries\n */\nexport function createStreamingPipeline(\n  boundaries: Map<string, StreamConfig>\n): Array<[string, StreamConfig]> {\n  const entries = Array.from(boundaries.entries());\n\n  return entries.sort((a, b) => {\n    const priorityA = getPriorityValue(a[1].priority);\n    const priorityB = getPriorityValue(b[1].priority);\n    return priorityA - priorityB;\n  });\n}\n\n/**\n * Gets numeric priority value for sorting.\n */\nfunction getPriorityValue(priority: StreamPriority | `${StreamPriority}`): number {\n  const values: Record<string, number> = {\n    critical: 0,\n    high: 1,\n    normal: 2,\n    low: 3,\n  };\n  return values[priority] ?? 2;\n}\n\n/**\n * Creates a flush schedule based on priorities.\n *\n * @description\n * Generates a schedule for when to flush content to the client\n * based on boundary priorities and defer times.\n *\n * @param boundaries - Boundary configurations\n * @returns Flush schedule with timing\n */\nexport interface FlushScheduleEntry {\n  boundaryId: string;\n  priority: StreamPriority;\n  flushAfterMs: number;\n}\n\nexport function createFlushSchedule(boundaries: Map<string, StreamConfig>): FlushScheduleEntry[] {\n  const schedule: FlushScheduleEntry[] = [];\n\n  for (const [boundaryId, config] of boundaries) {\n    schedule.push({\n      boundaryId,\n      priority: (config.priority as StreamPriority) ?? StreamPriority.Normal,\n      flushAfterMs: config.deferMs ?? 0,\n    });\n  }\n\n  return schedule.sort((a, b) => {\n    // Sort by flush time, then by priority\n    if (a.flushAfterMs !== b.flushAfterMs) {\n      return a.flushAfterMs - b.flushAfterMs;\n    }\n    return getPriorityValue(a.priority) - getPriorityValue(b.priority);\n  });\n}\n\n// ============================================================================\n// Express-style Middleware Factory\n// ============================================================================\n\n/**\n * Request-like interface for middleware.\n */\nexport interface StreamingRequest {\n  url: string;\n  method: string;\n  headers: Record<string, string | string[] | undefined>;\n}\n\n/**\n * Response-like interface for middleware.\n */\nexport interface StreamingResponse {\n  setHeader: (name: string, value: string) => void;\n  write: (chunk: string | Uint8Array) => boolean;\n  end: (chunk?: string | Uint8Array) => void;\n  flush?: () => void;\n  writableEnded?: boolean;\n}\n\n/**\n * Next function type for middleware.\n */\nexport type NextFunction = (error?: Error) => void;\n\n/**\n * Streaming middleware function type.\n */\nexport type StreamingMiddleware = (\n  req: StreamingRequest,\n  res: StreamingResponse,\n  next: NextFunction\n) => void | Promise<void>;\n\n/**\n * Creates streaming middleware for Express-style servers.\n *\n * @description\n * Factory function that creates middleware for setting up streaming\n * response handling with proper headers and context.\n *\n * @param options - Middleware options\n * @returns Middleware function\n *\n * @example\n * ```typescript\n * const streamingMiddleware = createStreamingMiddleware({\n *   compress: true,\n *   enableEarlyHints: true,\n * });\n *\n * app.use(streamingMiddleware);\n * ```\n */\nexport function createStreamingMiddleware(\n  options: Partial<StreamingMiddlewareOptions> = {}\n): StreamingMiddleware {\n  const mergedOptions = { ...DEFAULT_MIDDLEWARE_OPTIONS, ...options };\n\n  return (req, res, next) => {\n    // Set streaming headers\n    const headers = createStreamingHeaders(mergedOptions);\n    for (const [key, value] of Object.entries(headers)) {\n      res.setHeader(key, value);\n    }\n\n    // Create stream context and attach to request\n    const context = createServerStreamContext(\n      (chunk) => res.write(chunk),\n      () => res.flush?.(),\n      mergedOptions\n    );\n\n    // Attach context to request for use in route handlers\n    (req as StreamingRequest & { streamContext: ServerStreamContext }).streamContext = context;\n\n    // Set up timeout\n    if (mergedOptions.timeoutMs > 0) {\n      setTimeout(() => {\n        if (res.writableEnded !== true) {\n          context.end();\n        }\n      }, mergedOptions.timeoutMs);\n    }\n\n    next();\n  };\n}\n\n// ============================================================================\n// React SSR Integration Helpers\n// ============================================================================\n\n/**\n * Options for React streaming render.\n */\nexport interface RenderToStreamOptions {\n  /** Bootstrap scripts to include */\n  bootstrapScripts?: string[];\n  /** Bootstrap modules to include */\n  bootstrapModules?: string[];\n  /** CSP nonce for inline scripts */\n  nonce?: string;\n  /** Called when shell is ready */\n  onShellReady?: () => void;\n  /** Called when shell errors */\n  onShellError?: (error: Error) => void;\n  /** Called when all content is ready */\n  onAllReady?: () => void;\n  /** Called on any error */\n  onError?: (error: Error) => void;\n}\n\n/**\n * Creates options for React 18's renderToPipeableStream.\n *\n * @description\n * Generates configuration compatible with React 18's streaming SSR API.\n *\n * @param options - Render options\n * @returns Options for renderToPipeableStream\n *\n * @example\n * ```typescript\n * import { renderToPipeableStream } from 'react-dom/server';\n *\n * const streamOptions = createReactStreamOptions({\n *   bootstrapScripts: ['/app.js'],\n *   nonce: generateNonce(),\n *   onShellReady() {\n *     res.statusCode = 200;\n *     stream.pipe(res);\n *   },\n * });\n *\n * const { pipe } = renderToPipeableStream(<App />, streamOptions);\n * ```\n */\nexport function createReactStreamOptions(\n  options: RenderToStreamOptions = {}\n): RenderToStreamOptions {\n  return {\n    bootstrapScripts: options.bootstrapScripts,\n    bootstrapModules: options.bootstrapModules,\n    nonce: options.nonce,\n    onShellReady: options.onShellReady,\n    onShellError: (error) => {\n      console.error('[StreamingSSR] Shell error:', error);\n      options.onShellError?.(error);\n    },\n    onAllReady: options.onAllReady,\n    onError: (error) => {\n      console.error('[StreamingSSR] Error:', error);\n      options.onError?.(error);\n    },\n  };\n}\n\n/**\n * Creates the shell HTML for streaming SSR.\n *\n * @description\n * Generates the initial HTML shell that will be sent before\n * streaming content begins.\n *\n * @param options - Shell configuration\n * @returns HTML shell string\n */\nexport interface ShellOptions {\n  /** Document title */\n  title?: string;\n  /** Language attribute */\n  lang?: string;\n  /** Meta tags */\n  meta?: Array<Record<string, string>>;\n  /** Link tags (stylesheets, preloads) */\n  links?: Array<Record<string, string>>;\n  /** Inline styles */\n  styles?: string;\n  /** CSP nonce */\n  nonce?: string;\n  /** Initial state to embed */\n  initialState?: Record<string, unknown>;\n  /** Root element ID */\n  rootId?: string;\n}\n\nexport function createShellHtml(options: ShellOptions = {}): {\n  head: string;\n  bodyStart: string;\n  bodyEnd: string;\n} {\n  const {\n    title = '',\n    lang = 'en',\n    meta = [],\n    links = [],\n    styles = '',\n    nonce,\n    initialState,\n    rootId = 'root',\n  } = options;\n\n  const nonceAttr = nonce != null && nonce !== '' ? ` nonce=\"${nonce}\"` : '';\n\n  // Build meta tags\n  const metaTags = meta\n    .map((attrs) => {\n      const attrStr = Object.entries(attrs)\n        .map(([key, value]) => `${key}=\"${value}\"`)\n        .join(' ');\n      return `<meta ${attrStr}>`;\n    })\n    .join('\\n    ');\n\n  // Build link tags\n  const linkTags = links\n    .map((attrs) => {\n      const attrStr = Object.entries(attrs)\n        .map(([key, value]) => `${key}=\"${value}\"`)\n        .join(' ');\n      return `<link ${attrStr}>`;\n    })\n    .join('\\n    ');\n\n  // Build initial state script\n  const stateScript = initialState\n    ? `<script${nonceAttr}>window.__INITIAL_STATE__=${JSON.stringify(initialState)}</script>`\n    : '';\n\n  // Build style tag\n  const styleTag = styles ? `<style${nonceAttr}>${styles}</style>` : '';\n\n  return {\n    head: `<!DOCTYPE html>\n<html lang=\"${lang}\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    ${metaTags}\n    ${title ? `<title>${title}</title>` : ''}\n    ${linkTags}\n    ${styleTag}\n    ${stateScript}\n</head>`,\n    bodyStart: `<body>\n    <div id=\"${rootId}\">`,\n    bodyEnd: `</div>\n</body>\n</html>`,\n  };\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { DEFAULT_MIDDLEWARE_OPTIONS, STREAMING_HEADERS };\n"],"names":["DEFAULT_MIDDLEWARE_OPTIONS","generateNonce","STREAMING_HEADERS","array","i","byte","createServerStreamContext","writer","flush","options","mergedOptions","requestId","nonce","headers","key","value","chunk","error","createStreamingHeaders","createEarlyHints","resources","resource","hint","serializeStreamState","boundaryId","content","metadata","StreamState","calculateChecksum","createHydrationScript","states","data","deserializeStreamState","state","StreamMarkers","config","attrs","message","escaped","createServerChunk","sequence","isFinal","wrapBoundaryContent","nonceAttr","priority","StreamPriority","createStreamingPipeline","boundaries","a","b","priorityA","getPriorityValue","priorityB","createFlushSchedule","schedule","createStreamingMiddleware","req","res","next","context","createReactStreamOptions","createShellHtml","title","lang","meta","links","styles","initialState","rootId","metaTags","linkTags","stateScript","styleTag"],"mappings":"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"}