Files
2026-05-27 23:29:53 +01:00

6.0 KiB

OpenSpec Change: enterprise-api-docs

  • Change ID: enterprise-api-docs
  • Package: @suaveplan/api-docs
  • Category: universal/docs
  • Target path: universal/docs/api-docs
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/api-docs.md

Summary

Deliver @suaveplan/api-docs on the genesis branch from scratch at enterprise quality. The package provides an API documentation generator: parse TypeDoc-annotated TypeScript source, extract public API surfaces (functions, classes, interfaces, type aliases, enumerations), generate structured documentation as JSON/Markdown/HTML, and emit OpenAPI 3.1 schemas from function signatures. Genesis adds structured errors via @suaveplan/error, Zod schemas for all doc types, OTel instrumentation on generation operations, AbortSignal on async generation, injectable Clock for build timestamps, and a plugin interface for custom output formatters.


Current-state audit (genesis)

The package does not exist on genesis yet — this is a fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) Base class for ApiDocsError; stable error codes
@suaveplan/types (workspace:^) LoggerLike, Clock injectable interfaces
@suaveplan/logger (workspace:^) Structured logging with OTel trace correlation
@suaveplan/serialize (workspace:^) Structured serialization for doc export
zod (catalog:forms) Zod schemas for all public doc types
@opentelemetry/api (catalog:observability) Spans + counters on doc generation
tslib (catalog:build) Runtime helpers

Dev deps: vitest, @vitest/coverage-istanbul, fast-check (all catalog:testing).


Public API surface

Core

function createDocGenerator(options?: DocGeneratorOptions): DocGenerator

interface DocGenerator {
  generate(input: DocInput, signal?: AbortSignal): Promise<DocOutput>
  use(formatter: DocFormatter): this
}

Input/output types

interface DocInput {
  source: string | string[]         // file paths or glob patterns
  entryPoints?: string[]
  tsconfig?: string
  includePrivate?: boolean
  includeInternal?: boolean
}

interface DocOutput {
  readonly packages: ReadonlyArray<PackageDoc>
  readonly generatedAt: number
  toJSON(): string
  toMarkdown(): string
  toOpenApi(): OpenApiSchema
}

interface PackageDoc {
  readonly name: string
  readonly version?: string
  readonly description?: string
  readonly symbols: ReadonlyArray<SymbolDoc>
}

type SymbolDoc =
  | FunctionDoc
  | ClassDoc
  | InterfaceDoc
  | TypeAliasDoc
  | EnumDoc
  | VariableDoc

interface BaseSymbol {
  name: string
  kind: SymbolKind
  description?: string
  remarks?: string
  examples?: string[]
  deprecated?: string
  since?: string
  tags?: Record<string, string>
  sourceFile?: string
  sourceLine?: number
}

type SymbolKind = 'function' | 'class' | 'interface' | 'typeAlias' | 'enum' | 'variable'

interface FunctionDoc extends BaseSymbol {
  kind: 'function'
  signatures: ReadonlyArray<FunctionSignature>
}

interface FunctionSignature {
  parameters: ReadonlyArray<ParameterDoc>
  returnType: string
  typeParameters?: ReadonlyArray<TypeParameterDoc>
  overload?: number
}

interface ClassDoc extends BaseSymbol {
  kind: 'class'
  constructors: ReadonlyArray<FunctionSignature>
  properties: ReadonlyArray<PropertyDoc>
  methods: ReadonlyArray<FunctionDoc>
  extends?: string
  implements?: string[]
}

interface InterfaceDoc extends BaseSymbol {
  kind: 'interface'
  properties: ReadonlyArray<PropertyDoc>
  methods: ReadonlyArray<FunctionDoc>
  extends?: string[]
}

Plugin interface

interface DocFormatter {
  readonly name: string
  readonly format: 'json' | 'markdown' | 'html' | 'openapi' | string
  format(output: DocOutput): string | Promise<string>
}

function defineFormatter(formatter: DocFormatter): DocFormatter

Options

interface DocGeneratorOptions {
  logger?: LoggerLike
  clock?: Clock
  outputFormat?: 'json' | 'markdown' | 'html' | 'openapi'
  excludePatterns?: string[]
  includePatterns?: string[]
}

Error codes

type ApiDocsErrorCode =
  | 'API_DOCS_SOURCE_NOT_FOUND'
  | 'API_DOCS_PARSE_FAILED'
  | 'API_DOCS_GENERATE_FAILED'
  | 'API_DOCS_FORMATTER_NOT_FOUND'
  | 'API_DOCS_INVALID_INPUT'

function registerApiDocsErrorCodes(): void

Genesis additions

  1. Structured ApiDocsError extending SuaveplanError with stable API_DOCS.* codes
  2. Zod schemas for DocInput, DocGeneratorOptions, PackageDoc
  3. Plugin formatter interface — use() on DocGenerator; JSON, Markdown, and OpenAPI formatters built-in
  4. AbortSignal on generate()
  5. Injectable Clock for generatedAt timestamps
  6. OTel instrumentation — span api_docs.generate, histogram api_docs.generation_duration_ms, counter api_docs.symbols_parsed_total
  7. OpenAPI 3.1 emission from function signatures

File layout

universal/docs/api-docs/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/
      index.ts
    types/
      common.ts
      common.md
    core/
      generator/
        generator.ts
        generator.md
        generator.types.ts
        generator.test.ts
        index.ts
      parser/
        parser.ts
        parser.md
        parser.test.ts
        index.ts
    formatters/
      json-formatter/
        json-formatter.ts
        json-formatter.md
        json-formatter.test.ts
        index.ts
      markdown-formatter/
        markdown-formatter.ts
        markdown-formatter.md
        markdown-formatter.test.ts
        index.ts
      openapi-formatter/
        openapi-formatter.ts
        openapi-formatter.md
        openapi-formatter.test.ts
        index.ts
  tests/
    integration.test.ts

Impact

Downstream packages: @suaveplan/docs may depend on this for documentation site generation.

Workspace dep prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/logger, @suaveplan/serialize must be published.