postprocess.ts

Post-processing for analyzed library metadata.

These functions transform analysis results after module-level analysis is complete:

1. Validation — findDuplicates checks flat namespace constraints 2. Transformation — mergeReExports resolves re-export relationships, computeDependents builds bidirectional dependency graphs 3. Output — sortModules prepares deterministic output

@see analyze.ts for the main analysis entry point

Declarations
#

7 declarations

view source

computeDependents
#

postprocess.ts view source

(files: readonly SourceFileInfo[]): (SourceFileInfo & { dependents?: readonly string[] | undefined; })[]

Compute bidirectional dependencies from source files.

This function ensures that if file A has file B in its dependencies, then file B will have file A in its dependents. This provides consistent output regardless of whether callers provide one-directional or bidirectional dependency information.

Returns new SourceFileInfo objects when computed dependents exist or when paths needed posixification; otherwise the original input objects flow through ===-equal (fast path for session callers, who already pass POSIX paths and may have no inferable dependents for a given file).

files

source files with optional dependency information

type readonly SourceFileInfo[]

returns

(SourceFileInfo & { dependents?: readonly string[] | undefined; })[]

new array with bidirectional dependencies computed

examples

// Input: Calculator.svelte has dependencies: [math.ts] // Output: Calculator.svelte has dependencies: [math.ts] // math.ts has dependents: [Calculator.svelte] const filesWithBidirectional = computeDependents(files);

DuplicateDeclaration
#

postprocess.ts view source

DuplicateDeclaration

A duplicate declaration with its full metadata and module path.

declaration

The full declaration metadata.

module

Module path where this declaration is defined.

type string

findDuplicates
#

postprocess.ts view source

(modules: { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: string | undefined; }[]): Map<...>

Find duplicate declaration names across modules.

Callers can decide how to handle duplicates (throw, warn, ignore).

modules

type { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: ...

returns

Map<string, DuplicateDeclaration[]>

Map of declaration names to their DuplicateDeclaration occurrences (only includes duplicates)

examples

const duplicates = findDuplicates(modules); if (duplicates.size > 0) { for (const [name, occurrences] of duplicates) { console.error(`"${name}" found in:`); for (const {declaration, module} of occurrences) { console.error(` - ${module}:${declaration.sourceLine} (${declaration.kind})`); } } throw new Error(`Found ${duplicates.size} duplicate declaration names`); }

mergeReExports
#

postprocess.ts view source

(modules: { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: string | undefined; }[], collectedReExports: ReExportEntry[]): void

Build alsoExportedFrom arrays from collected re-export data.

This function resolves the two-phase re-export problem:

Problem: When module A re-exports from module B, we discover this while analyzing A, but need to update B's declarations. However, B may already be processed or may be processed later.

Solution: Collect all re-exports in phase 1, then merge them in phase 2 after all modules are analyzed.

Component-only fields on renamed component aliases (props, acceptsChildren, etc.) are populated separately by resolveComponentAliases — call it after this function. They split because they touch disjoint fields and have different inputs.

modules

the modules array with all modules (will be mutated)

type { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: ...

collectedReExports

array of re-exports collected during phase 1

type ReExportEntry[]

returns

void

examples

// helpers.ts exports: foo, bar // index.ts does: export {foo, bar} from './files.js' // // After processing: // - helpers.ts foo declaration gets: alsoExportedFrom: ['index.ts'] // - helpers.ts bar declaration gets: alsoExportedFrom: ['index.ts']

ReExportEntry
#

postprocess.ts view source

ReExportEntry

A collected re-export with its source module context.

Used during the two-phase re-export resolution: 1. Phase 1: Collect re-exports from each module during analysis 2. Phase 2: Group by original module and merge into alsoExportedFrom

reExportingModule

The module that re-exports the declaration.

type string

reExport

The re-export info (name and original module).

resolveComponentAliases
#

postprocess.ts view source

(modules: { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: string | undefined; }[]): void

Copy props/acceptsChildren/lang/etc. from canonical component declarations onto synthesized component-aliased declarations.

Renamed Svelte component re-exports (export {default as Foo} from './X.svelte') are emitted as kind: 'component' placeholders by analyzeExports, with aliasOf pointing at the canonical. The canonical's component-specific fields are only available after analyzeSvelteModule synthesizes the canonical declaration, so the copy happens here in phase 2 once all modules are analyzed.

Call this *after* mergeReExports — both walk the same modules array but read/write disjoint fields, so order between them only matters for clarity.

modules

type { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: ...

returns

void

sortModules
#

postprocess.ts view source

(modules: { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: string | undefined; }[]): { ...; }[]

Sort modules alphabetically by path for deterministic output and cleaner diffs.

modules

the modules to sort

type { path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: ...

returns

{ path: string; declarations: ({ kind: "function"; parameters: { name: string; type: string; optional: boolean; rest: boolean; description?: string | undefined; defaultValue?: string | undefined; }[]; ... 17 more ...; sourceLine?: number | undefined; } | ... 7 more ... | { ...; })[]; ... 4 more ...; moduleComment?: ...

a new sorted array (does not mutate input)

Depends on
#

Imported by
#