MUI Docs Infra

Warning

This is an internal project, and is not intended for public use. No support or stability guarantees are provided.

Load Server Types Meta

The core server-side function for loading and formatting TypeScript type metadata. This function extracts types from your source files and returns structured data ready for documentation generation or rendering.

Overview

loadServerTypesMeta handles the TypeScript → formatted types pipeline:

  • Loads and caches TypeScript configuration with file-watcher invalidation
  • Resolves library source files, supporting relative paths, tsconfig path aliases, and external packages
  • Discovers DataAttributes and CssVars meta files from entrypoints and re-exported directories
  • Extracts types via a dedicated worker thread with a cached in-memory TypeScript language service
  • Formats components, hooks, functions, classes, and raw types into structured metadata
  • Rewrites type references to canonical namespaced names for re-exported component libraries
  • Deduplicates types, groups by component, and organizes exports for UI consumption

This function is separated from syncTypes to allow direct access to formatted types without markdown generation. Use this when you need type metadata but don't need to write a types.md file.

This function and loadServerTypesText both produce a TypesSourceData structure — the shared contract that loadServerTypes consumes. See the loadServerTypes overview for details on this shared structure.

Note: Type highlighting is handled separately by loadServerTypes, which calls syncTypes (which uses this function) and then applies highlightTypes and highlightTypesMeta to convert plain text types to syntax-highlighted HAST.

Usage

Basic Usage

import { loadServerTypesMeta } from '@mui/internal-docs-infra/pipeline/loadServerTypesMeta';

const result = await loadServerTypesMeta({
  typesMarkdownPath: '/absolute/path/to/types.md',
  rootContext: '/absolute/path/to/project',
  variants: { Default: '@base-ui/react/checkbox' },
  formattingOptions: {
    shortTypeUnionPrintWidth: 40,
    defaultValueUnionPrintWidth: 40,
  },
});

// Organized type exports (e.g., { Root: { type, additionalTypes }, Trigger: { type, additionalTypes } })
result.exports;
// Top-level types not attached to a specific export (e.g., standalone type aliases)
result.additionalTypes;
// Files to watch for changes
result.allDependencies;
// External types referenced in props but not publicly exported (e.g., Orientation = 'horizontal' | 'vertical')
result.externalTypes;
// Derived name for display
result.resourceName;

Multiple Variants

When documenting types from multiple exports, pass each as a separate variant entry. Each variant is a named entrypoint whose types are extracted independently then merged:

const result = await loadServerTypesMeta({
  typesMarkdownPath: '/absolute/path/to/types.md',
  rootContext: '/absolute/path/to/project',
  variants: {
    Checkbox: '@base-ui/react/checkbox',
    Button: '@base-ui/react/button',
  },
});

// Which type names originated from each variant
result.variantTypeNames; // { Checkbox: ['Root', 'Root.Props', ...], Button: ['Root', ...] }
// Per-variant typeNameMaps (flat name → dotted name)
result.variantTypeNameMaps;

Filtering Descriptions

Use descriptionReplacements to transform or strip patterns from extracted JSDoc descriptions. Each entry specifies a regex pattern, a replacement string, and optional flags. Replacements are applied to all descriptions: components, hooks, functions, classes, props, parameters, enum members, and raw types.

const result = await loadServerTypesMeta({
  typesMarkdownPath: '/absolute/path/to/types.md',
  rootContext: '/absolute/path/to/project',
  variants: { Default: '@base-ui/react/checkbox' },
  // Strip "Documentation: <url>" suffixes from descriptions
  descriptionReplacements: [{ pattern: '\\n\\nDocumentation:.*$', replacement: '', flags: 'm' }],
});

Filtering External Types

By default, all qualifying external types (named unions of literals referenced in props) are collected. Use externalTypesPattern to limit which ones are included:

const result = await loadServerTypesMeta({
  typesMarkdownPath: '/absolute/path/to/types.md',
  rootContext: '/absolute/path/to/project',
  variants: { Default: '@base-ui/react/checkbox' },
  externalTypesPattern: '^(Orientation|Alignment|Side)$',
});
FunctionPurposeWrites FilesReturns
loadServerTypesMetaLoad & format typesOrganized plain-text types
syncTypesSync types.md file✅ types.mdPlain-text types + exports structure
loadServerTypesFull pipeline with highlighting✅ types.mdHAST-highlighted types

Performance

First Request

~500-1200ms to create the TypeScript program and parse types (depends on project size)

Subsequent Requests

~100-140ms using the cached language service and file data

Multi-Process Improvement

~87-92% improvement vs. creating separate language services per process, thanks to the socket-based IPC sharing a single TypeScript program

Processing Pipeline

1. Load TypeScript Configuration

Loads tsconfig.json with support for extends inheritance. Results are cached with a file watcher that invalidates the cache on changes, so config updates take effect without restarting the dev server.

2. Resolve Library Source Files

Resolves variant paths to actual file system locations, handling three categories:

  • Relative paths — files within the project root, resolved via filesystem
  • Path-mapped imports — resolved through tsconfig paths configuration (e.g., @base-ui/react/*)
  • External library imports — resolved through Node.js module resolution. When watchSourceDirectly is enabled (auto-detected when tsconfig path aliases are used), follows .d.ts.map source maps to locate the original TypeScript source files instead of declaration files.

3. Find Meta Files

Recursively walks entrypoint directories and re-exported directories to discover DataAttributes and CssVars files. Re-exported directories are found by parsing relative exports (e.g., export * from '../menu/') from the entrypoint source files.

4. Process Types in Worker

Type extraction is offloaded to a dedicated worker thread. Inside the worker:

  • Creates an optimized TypeScript program using an in-memory LanguageServiceHost singleton that caches file contents and tracks versions for incremental updates
  • Parses exports using typescript-api-extractor's parseFromProgram, which extracts components, hooks, functions, classes, type aliases, and interfaces with their full type trees
  • Builds a type name map from flat export names to their dotted equivalents (e.g., AccordionRootStateAccordion.Root.State), only when both the flat and dotted names exist as exports
  • Parses meta files separately to include DataAttributes/CssVars type info that isn't imported from the entrypoint
  • Collects dependencies by walking the import graph from each entrypoint for HMR file watching
  • Strips functions from the result for serialization across the worker boundary (structured clone can't handle functions)

5. Build Type Compatibility Map

Before formatting, builds a map from original type names to their canonical export names. This map is derived from two sources on the parsed exports:

  • reexportedFrom — when a component is re-exported under a new name (e.g., AlertDialog.Trigger re-exports DialogTrigger)
  • extendsTypes — when an interface extends another (e.g., AlertDialog.Root.Props extends Dialog.Props)

This map drives the type rewriting in the next step, ensuring that type references in documentation use the canonical namespaced names rather than internal names from the source library.

6. Format Types

Converts raw TypeScript exports to formatted metadata based on their detected category:

  • Components (formatComponentData) — extracts props, data attributes, CSS variables. Matches DataAttributes/CssVars by original component name, with a fallback that searches by short name and prefers candidates whose prefix appears in the component's namespace.
  • Hooks (formatHookData) — extracts parameters/properties and return value. Handles overloads by picking the longest signature and marking extra parameters as optional.
  • Functions (formatFunctionData) — same structure as hooks, without the use name prefix requirement.
  • Classes (formatClassData) — extracts constructor parameters, properties, and methods.
  • Raw types (formatRawData) — formats the type declaration as code. Special handling for enums (member tables), DataAttributes, and CssVars types.

Each formatter calls rewriteTypeStringsDeep at the end, which applies the type compatibility map from step 5 to normalize all type references. Rewrites use word-boundary matching to prevent partial replacements (e.g., Dialog won't match inside AlertDialog).

During formatting, formatType also collects external types — types referenced in props that aren't publicly exported from the component's module. This includes named union types (e.g., Orientation = 'horizontal' | 'vertical'), named function types, and external type references that resolve to unions or literals. Collection happens inline during type formatting rather than as a separate tree walk, so only types that actually appear in the formatted output are collected.

Note: When a hook or function has a single anonymous object parameter (e.g., function useHook(params: { enabled: boolean })), the object's fields are expanded into individual properties instead of being listed as a single parameter. This provides a cleaner documentation layout for options-style APIs.

7. Group by Component

For single-variant exports with sub-components (e.g., Accordion.Root, Accordion.Trigger), groups types by component:

// Before: { Default: { types: [Accordion.Root, Accordion.Trigger, ...] } }
// After: { "Accordion.Root": { types: [...] }, "Accordion.Trigger": { types: [...] } }

Grouping only activates when there are actual sub-components — 2-part names that are components, hooks, functions, or classes (not just raw type suffixes like Button.Props). Once active:

  • 3+ part names (e.g., Accordion.Root.State): grouped under the first two parts (Accordion.Root)
  • 2-part component/hook/function/class (e.g., Accordion.Root): becomes its own group
  • 2-part raw types (e.g., Toolbar.Orientation): remain in the "Default" group
  • 1-part names (e.g., DirectionProvider): remain in the "Default" group

8. Deduplicate and Normalize

Several normalization passes clean up the type list:

  • Deduplication — when the same type name appears multiple times (e.g., DirectionProvider exported from both index.ts and DirectionProvider.tsx), keeps one entry, preferring component/hook types over raw types
  • Flat name filtering — removes flat-named types when a namespaced version exists (e.g., removes AccordionRootState when Accordion.Root.State is present), since the type name map confirms they represent the same type
  • Alias attachment — adds flat names as lookup aliases on the remaining namespaced types (e.g., Accordion.Root.State gets alias AccordionRootState), so consumers can look up types by either name

9. Detect Re-exports

Identifies when raw type exports are re-exports of component data by matching the pattern {ComponentName}.{Suffix}:

  • Button.Props → marked as re-export of Button's props table
  • Checkbox.DataAttributes → marked as re-export of Checkbox's data attributes
  • Checkbox.CssVars → marked as re-export of Checkbox's CSS variables

10. Organize by Export

Types are organized into an exports structure for UI consumption via organizeTypesByExport, which separates main types (components, hooks, functions, classes) from additional types (raw types like Props, State) and computes slugs for anchor linking.

Worker Architecture

The function uses a worker-based architecture for efficient TypeScript processing:

Main Thread Responsibilities

  • Loading and caching TypeScript configuration
  • Path resolution and meta file discovery
  • Formatting types with type rewriting
  • Coordinating worker communication

Worker Thread Responsibilities

  • Creating and caching the TypeScript language service (in-memory LanguageServiceHost singleton)
  • Parsing exports with typescript-api-extractor
  • Building type name maps and collecting dependencies
  • Tracking file versions for incremental updates

The worker manager uses a Symbol.for() key on the process object to ensure the singleton persists across Turbopack module contexts, where each compilation gets a separate globalThis scope but shares the same Node.js process. The TypeScript language service in the worker uses a simpler globalThis singleton since worker threads have a single module context.

Socket-Based IPC

For multi-process environments (e.g., Next.js with multiple workers):

  • First worker acquires a lock and becomes the "server", holding the TypeScript language service
  • Other workers connect as "clients" via Unix domain socket (or named pipe on Windows)
  • All workers share a single TypeScript program instance, avoiding redundant memory usage
  • If the server becomes unavailable, clients fall back to local processing

Types

Loads and formats TypeScript types from source files.

This function handles:

  • Loading TypeScript configuration
  • Resolving library source files and variants
  • Finding meta files (DataAttributes, CssVars)
  • Processing types via worker thread
  • Formatting component, hook, function, and raw types
  • Collecting external types referenced in props/params

The result can be used by syncTypes for markdown generation or by other consumers.

PropertyTypeDescription
typesMarkdownPath
string

Absolute path to the types.md file (used for deriving paths)

rootContext
string

Root context directory (workspace root)

variants
Record<string, string> | undefined

Map of variant name to file path (relative or package path). Each variant is an entrypoint whose types are extracted independently then merged. For single component: { Default: '@base-ui/react/checkbox' } For multiple: { Checkbox: '@base-ui/react/checkbox', Button: '@base-ui/react/button' }

watchSourceDirectly
boolean | undefined

When true, resolves library paths to their source files for watching. Useful during development to watch the original source rather than built files.

formattingOptions
FormatInlineTypeOptions | undefined

Options for formatting types in tables

socketDir
string | undefined

Directory path for socket and lock files used for IPC between workers. Useful for Windows where the default temp directory may not support Unix domain sockets.

externalTypesPattern
string | undefined

Optional regex pattern string to filter which external types to include. External types are named union types (like Orientation = 'horizontal' | 'vertical') that are referenced in props but not exported from the component’s module.

When not provided, ALL qualifying named union types (unions of literals) will be collected automatically. This is the recommended behavior for most projects.

When provided, only external types whose names match this pattern will be collected.

ordering
OrderingConfig | undefined

Custom ordering configuration for sorting props, data attributes, exports, etc.

descriptionReplacements
DescriptionReplacement[] | undefined

Pattern/replacement pairs to apply to JSDoc descriptions. Each entry has a pattern (regex string) and replacement string.

Return Type
ClassTypeMeta
type ClassTypeMeta = {
  name: string;
  description?: HastRoot;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /** Constructor parameters */
  constructorParameters: FormattedParameter[];
  /** Public instance properties */
  properties: Record<string, FormattedProperty>;
  /** Public instance methods */
  methods: Record<string, FormattedMethod>;
  /** Type parameters (generics) if any */
  typeParameters?: string[];
}
ComponentTypeMeta
type ComponentTypeMeta = {
  name: string;
  description?: HastRoot;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  props: Record<string, FormattedProperty>;
  dataAttributes: Record<string, FormattedEnumMember>;
  cssVariables: Record<string, FormattedEnumMember>;
}
DescriptionReplacement
type DescriptionReplacement = {
  /** Regex pattern string to match in descriptions */
  pattern: string;
  /** Replacement string (supports regex replacement syntax like $1) */
  replacement: string;
  /** Regex flags (e.g. 'g', 'm', 'gm'). Defaults to no flags. */
  flags?: string;
}
FormatInlineTypeOptions
type FormatInlineTypeOptions = {
  /**
   * Maximum line width before union types in shortType fields are split across multiple lines.
   * When a union type exceeds this width, it will be formatted with each
   * member on a separate line with leading pipe characters.
   * @default 40
   */
  shortTypeUnionPrintWidth?: number;
  /**
   * Maximum line width before union types in defaultValue fields are split across multiple lines.
   * When a union type exceeds this width, it will be formatted with each
   * member on a separate line with leading pipe characters.
   * @default 40
   */
  defaultValueUnionPrintWidth?: number;
  /**
   * Maximum line width for Prettier formatting of type definitions.
   * @default 60
   */
  typePrintWidth?: number;
}
FormattedEnumMember
type FormattedEnumMember = {
  /** Description of the enum member as parsed markdown HAST */
  description?: Root;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /**
   * Type annotation from JSDoc
   * @type tag
   */
  type?: string;
}
FormattedParameter
type FormattedParameter = {
  /** Parameter name */
  name: string;
  /** Plain text type string */
  typeText: string;
  /** Plain text default value */
  defaultText?: string;
  /** Whether the parameter is optional */
  optional?: true;
  /** Description from JSDoc as parsed markdown HAST */
  description?: Root;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /** Example usage as parsed markdown HAST */
  example?: Root;
  /** Plain text version of example for markdown generation */
  exampleText?: string;
  /** @see as parsed markdown HAST */
  see?: Root;
  /**
   * Plain text version of
   * @see for markdown generation
   */
  seeText?: string;
}
FormattedProperty
type FormattedProperty = {
  /** Plain text type string */
  typeText: string;
  /** Plain text default value */
  defaultText?: string;
  /** Whether the property is required */
  required?: true;
  /** Description as parsed markdown HAST */
  description?: Root;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /** Example usage as parsed markdown HAST */
  example?: Root;
  /** Plain text version of example for markdown generation */
  exampleText?: string;
  /** @see as parsed markdown HAST */
  see?: Root;
  /**
   * Plain text version of
   * @see for markdown generation
   */
  seeText?: string;
}
FunctionTypeMeta
type FunctionTypeMeta = {
  name: string;
  description?: HastRoot;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /** Ordered function parameters */
  parameters?: FormattedParameter[];
  /**
   * Expanded properties from a single anonymous object parameter.
   * When populated, `parameters` should be omitted and headings should
   * say "Properties" instead of "Parameters".
   */
  expandedProperties?: Record<string, FormattedProperty>;
  /** Return value - either plain text string or object with properties (like hook return values) */
  returnValue: Record<string, FormattedProperty> | string;
  /** Plain text version of returnValue for markdown generation (when returnValue is string) */
  returnValueText?: string;
  /** Description of the return value (parsed markdown as HAST) */
  returnValueDescription?: HastRoot;
  /** Plain text version of returnValueDescription for markdown generation */
  returnValueDescriptionText?: string;
}
HookTypeMeta
type HookTypeMeta = {
  name: string;
  description?: HastRoot;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /** Ordered function parameters */
  parameters?: FormattedParameter[];
  /**
   * Expanded properties from a single anonymous object parameter.
   * When populated, `parameters` should be omitted and headings should
   * say "Properties" instead of "Parameters".
   */
  expandedProperties?: Record<string, FormattedProperty>;
  returnValue: Record<string, FormattedProperty> | string;
  /** Plain text version of returnValue for markdown generation (when returnValue is string) */
  returnValueText?: string;
  /** Description of the return value (parsed markdown as HAST) */
  returnValueDescription?: HastRoot;
  /** Plain text version of returnValueDescription for markdown generation */
  returnValueDescriptionText?: string;
}
LoadServerTypesMetaOptions
type LoadServerTypesMetaOptions = {
  /** Absolute path to the types.md file (used for deriving paths) */
  typesMarkdownPath: string;
  /** Root context directory (workspace root) */
  rootContext: string;
  /**
   * Map of variant name to file path (relative or package path).
   * Each variant is an entrypoint whose types are extracted independently then merged.
   * For single component: `{ Default: '@base-ui/react/checkbox' }`
   * For multiple: `{ Checkbox: '@base-ui/react/checkbox', Button: '@base-ui/react/button' }`
   */
  variants?: Record<string, string>;
  /**
   * When true, resolves library paths to their source files for watching.
   * Useful during development to watch the original source rather than built files.
   */
  watchSourceDirectly?: boolean;
  /** Options for formatting types in tables */
  formattingOptions?: FormatInlineTypeOptions;
  /**
   * Directory path for socket and lock files used for IPC between workers.
   * Useful for Windows where the default temp directory may not support Unix domain sockets.
   */
  socketDir?: string;
  /**
   * Optional regex pattern string to filter which external types to include.
   * External types are named union types (like `Orientation = 'horizontal' | 'vertical'`)
   * that are referenced in props but not exported from the component's module.
   *
   * When not provided, ALL qualifying named union types (unions of literals) will be
   * collected automatically. This is the recommended behavior for most projects.
   *
   * When provided, only external types whose names match this pattern will be collected.
   * @example undefined // Collect all qualifying external types (recommended)
   * @example '^(Orientation|Alignment|Side)$' // Only include specific types
   */
  externalTypesPattern?: string;
  /** Custom ordering configuration for sorting props, data attributes, exports, etc. */
  ordering?: OrderingConfig;
  /**
   * Pattern/replacement pairs to apply to JSDoc descriptions.
   * Each entry has a `pattern` (regex string) and `replacement` string.
   */
  descriptionReplacements?: DescriptionReplacement[];
}
LoadServerTypesMetaResult
type LoadServerTypesMetaResult = {
  /** All dependencies that should be watched for changes */
  allDependencies: string[];
  /** Type name map from variant processing */
  typeNameMap?: Record<string, string>;
  /**
   * External types discovered during formatting.
   * These are types referenced in props/params that are not publicly exported,
   * but whose definitions are useful for documentation (e.g., union types).
   * Map from type name to its definition string.
   */
  externalTypes: Record<string, string>;
  /** Resource name derived from the types path */
  resourceName: string;
  /** Export data where each export has a main type and related additional types */
  exports: Record<string, { type: TypesMeta; additionalTypes: TypesMeta[] }>;
  /** Top-level non-namespaced types not claimed by any variant-only group */
  additionalTypes: TypesMeta[];
  /**
   * Types belonging to variant-only groups (variants with no main export).
   * Keyed by variant name, each entry contains the types from that variant.
   * These are separated from `additionalTypes` to avoid duplication.
   */
  variantOnlyAdditionalTypes: Record<string, TypesMeta[]>;
  /**
   * Maps variant names to the type names that originated from that variant.
   * Used for namespace imports (e.g., `* as Types`) to filter additionalTypes
   * to only show types from that specific module.
   */
  variantTypeNames: Record<string, string[]>;
  /**
   * Maps variant names to their per-variant typeNameMaps.
   * Used for Canonical Types annotations showing which variants contain each type.
   */
  variantTypeNameMaps: Record<string, Record<string, string>>;
}
RawTypeMeta
type RawTypeMeta = {
  /** Display name for this type (may include dots like "Component.Root.State") */
  name: string;
  /** Description parsed from JSDoc as HAST */
  description?: HastRoot;
  /** Plain text version of description for markdown generation */
  descriptionText?: string;
  /**
   * The formatted type declaration as plain text (e.g., "type ButtonProps = { ... }").
   * Will be highlighted to HAST in loadServerTypes.
   */
  formattedCode: string;
  /**
   * For enum types, the individual members with their values and descriptions.
   * When present, indicates this type should be rendered as an enum table.
   */
  enumMembers?: EnumMemberMeta[];
  /**
   * For re-exports, information about the component this type re-exports from.
   * When set, indicates this should be rendered as a link to the component.
   */
  reExportOf?: ReExportInfo;
  /** For DataAttributes types, the component name this type belongs to. */
  dataAttributesOf?: string;
  /** For CssVars types, the component name this type belongs to. */
  cssVarsOf?: string;
  /**
   * For object types, the individual properties with their types and descriptions.
   * Used by the enhancement stage to convert named return type references into property tables.
   */
  properties?: Record<string, FormattedProperty>;
}
ReExportInfo
type ReExportInfo = {
  /** Display name of the component (e.g., "Trigger" from "Accordion.Trigger") */
  name: string;
  /** Anchor slug for linking (e.g., "#trigger") */
  slug: string;
  /** What kind of type this re-exports */
  suffix: 'props' | 'css-variables' | 'data-attributes';
}
TypesMeta
type TypesMeta = (
  | { type: 'class'; data: ClassTypeMeta }
  | { type: 'component'; data: ComponentTypeMeta }
  | { type: 'hook'; data: HookTypeMeta }
  | { type: 'function'; data: FunctionTypeMeta }
  | { type: 'raw'; data: RawTypeMeta }
) & {
  name: string;
  slug?: string;
  /** Alternative names this type can be looked up by (e.g., flat export name like "AccordionRootState") */
  aliases?: string[];
}