@hyperfrontend/builder/bundle/declarations

declarations

tsc-driven .d.ts emission and post-emit path flattening.

generateDeclarations(context) shells out to the workspace-local tsc binary with --emitDeclarationOnly --declaration --declarationMap, captures stdout / stderr, and throws when the compiler exits with a non-zero status. After tsc finishes it calls flattenDeclarationPaths to relocate the nested dist/<lib>/libs/<lib>/src/... structure that tsc emits when baseUrl points at the workspace root back into the flat per-library shape consumers expect. The flatten is a recursive, unconditional copy of the whole nested src declaration tree, so internal non-entry subdirectories any entry's index.d.ts re-exports from (e.g. shared/, lib/) are preserved rather than dropped; it then removes the leftover libs/, plugins/, and apps/ folders left at the output root.

API Reference

ƒ Functions

§function

computeSiblingSpecifier(selfDtsPath: string, sibling: SiblingEntry): string

Computes the bare-specifier form of a sibling import as emitted in the rewritten .d.ts (e.g., ../models, ../../models, ./bundle/declarations).
Always omits the trailing index.d.ts so both moduleResolution: 'bundler' and node accept it.

Parameters

NameTypeDescription
§selfDtsPath
string
Absolute path to the current entry's index.d.ts.
§sibling
SiblingEntry
The sibling entry being targeted.

Returns

string
POSIX-style relative specifier ready for id in a rollup external resolution.

Example

Computing a sibling import from `bundle/index.d.ts` to `models/`

computeSiblingSpecifier(
  '/abs/dist/libs/foo/bundle/index.d.ts',
  { srcPath: 'models', indexDtsPath: '/abs/dist/libs/foo/models/index.d.ts' }
) // => '../models'
§function

createSiblingExternalizePlugin(input: SiblingResolverInput): Plugin

Returns a rollup plugin that externalizes any import resolving inside a sibling entry's directory tree, rewriting the emitted specifier to a POSIX relative path stripped of /index and .d.ts suffixes.
The plugin's resolveId hook returns null for everything that does not resolve into a sibling — that lets the rest of the rollup-plugin-dts chain inline third-party type imports as before.
Self-ownership is enforced by adding the current entry into the ownership pool: when the deepest-matching entry directory is the entry being rewritten (and not a sibling), the resolver returns null so rollup keeps the path internal. This matters for the package root entry whose directory prefix- matches every other entry's path — without including self, root would spuriously claim its own subtree's files.

Parameters

NameTypeDescription
§input
SiblingResolverInput
Self + sibling entry descriptors.

Returns

Plugin
Rollup plugin.

Example

Plugin instance for the bundle entry pass

const plugin = createSiblingExternalizePlugin({
  selfSrcPath: 'bundle',
  selfDtsPath: '/abs/dist/libs/foo/bundle/index.d.ts',
  siblings: [{ srcPath: 'models', indexDtsPath: '/abs/dist/libs/foo/models/index.d.ts' }],
})
§function

dtsPathFor(outputPath: string, srcPath: string): string

Joins an output base directory with an entry's srcPath to produce the absolute path of the entry's bundled index.d.ts.

Parameters

NameTypeDescription
§outputPath
string
Absolute output directory.
§srcPath
string
Entry's srcPath. '' for root.

Returns

string
Absolute path to <outputPath>/<srcPath>/index.d.ts.

Example

Computing the d.ts path for a sub-entry

dtsPathFor('/abs/dist/libs/foo', 'models') // => '/abs/dist/libs/foo/models/index.d.ts'
§function

filterSiblings<T>(srcPath: string, entries: T[]): T[]

Convenience: filters an entry list to siblings of the supplied srcPath.

Parameters

NameTypeDescription
§srcPath
string
The entry's srcPath to exclude.
§entries
T[]
All discovered entries.

Returns

T[]
Entries whose srcPath differs from the supplied one.

Example

Building the sibling list for `bundle/`

const siblings = filterSiblings('bundle', allEntries)
§function

findOwningSibling(absolutePath: string, siblings: SiblingEntry[]): SiblingEntry

Returns the sibling entry whose directory contains absolutePath, or undefined when no sibling owns the path.

Parameters

NameTypeDescription
§absolutePath
string
Resolved absolute path of an import.
§siblings
SiblingEntry[]
Sibling-entry records.

Returns

SiblingEntry
Owning sibling entry, or undefined.

Example

Identifying a sibling for a resolved type import

const owner = findOwningSibling('/abs/dist/libs/foo/models/index.d.ts', siblings)
§function

flattenDeclarationPaths(context: BuildContext): void

Reshapes the nested declaration tree produced by tsc (with baseUrl=workspaceRoot) into the flat per-library structure consumers expect.
Without this step tsc emits declarations at dist/libs/<lib>/libs/<lib>/src/index.d.ts because it preserves the workspace-relative path. This primitive flattens that to dist/libs/<lib>/index.d.ts while preserving any nested platform / feature subdirectories.
The copy is recursive and unconditional, so internal non-entry subdirectories that any entry's index.d.ts re-exports from (e.g. shared/, lib/) are preserved rather than dropped. Per-source declarations left unreachable once the per-entry pass inlines each index.d.ts are removed afterwards by pruneOrphanDeclarations. Finally removes the leftover libs/, plugins/, and apps/ folders tsc created at the output root.

Parameters

NameTypeDescription
§context
BuildContext
Resolved build context. Uses projectRoot, outputPath, and workspaceRoot.

Example

Flattening declarations after a manual tsc invocation

flattenDeclarationPaths(context)
§function

generateDeclarations(context: BuildContext): Promise<GenerateDeclarationsResult>

Generates .d.ts and .d.ts.map files for every entry point in the project by spawning the workspace-local TypeScript compiler.
After tsc finishes, calls flattenDeclarationPaths to relocate the nested dist/<lib>/libs/<lib>/src/... structure that tsc emits with baseUrl=workspaceRoot back into the flat per-library shape consumers expect.

Parameters

NameTypeDescription
§context
BuildContext
Resolved build context. Provides project root, output path, tsconfig path, workspace root, and entry point discovery for the flatten step.

Returns

Promise<GenerateDeclarationsResult>
Promise resolving with tsc's exit status, captured stdout, and captured stderr.

Example

Generating declarations as part of a custom build

const result = await generateDeclarations(context)
console.log(result.stdout)
§function

pruneOrphanDeclarations(context: BuildContext): number

Removes redundant per-source .d.ts / .d.ts.map files left behind once the per-entry flatten has inlined each entry's declarations into a self-contained index.d.ts.
Walks the whole package tree (excluding _dependencies/) and deletes every declaration file not reachable from an entry-point index.d.ts via its transitive relative specifiers. Reachability — rather than a per-directory sweep — guarantees the invariant that after this runs no surviving .d.ts references a removed one: when the flatten made index.d.ts self-contained the reachable set collapses to the roots and every per-source sibling is pruned; when the flatten was skipped the siblings the public entry still re-exports (and anything they transitively re-export) stay live so the shipped types resolve. This removes the redundancy at the source so dist == the shipped tarball, demoting package.json#files to a backstop.
Safety rails:
  • Never touches anything inside _dependencies/.
  • A .d.ts.map is kept iff its sibling .d.ts is reachable.
  • A dynamic (non-literal) import(/require( in any reached declaration
aborts the prune and keeps every declaration file.

Parameters

NameTypeDescription
§context
BuildContext
Resolved build context.

Returns

number
The total number of .d.ts / .d.ts.map files removed.

Example

Pruning orphans after generateDeclarations

const removed = pruneOrphanDeclarations(context)
§function

runDtsPerEntry(context: BuildContext, monitor?: MemoryMonitor): Promise<void>

Runs the per-entry d.ts inlining pass: re-runs rollup-plugin-dts over every tsc-emitted entry .d.ts so (a) local per-source sibling re-exports (export … from './create-logger') are flattened into the entry's index.d.ts, and (b) bundled-dep type imports are routed through _dependencies/<dep>/index.d.ts rather than left as bare specifiers. This self-containment is what lets pruneOrphanDeclarations delete the orphaned per-source .d.ts afterwards without orphaning a still-referenced sibling.
Runs whenever the build bundles any dep — npm (bundledDeps) or workspace (workspaceBundledDeps); a package whose deps are all @hyperfrontend/* still needs the flatten. Entries whose tsc output is missing are skipped silently — the bundle phase may have skipped them deliberately (e.g., empty bundles).

Parameters

NameTypeDescription
§context
BuildContext
Resolved build context.
§monitor?
MemoryMonitor
Optional memory monitor invoked between jobs.

Example

Inlining bundled-dep types into every entry's .d.ts after tsc emission

await runDtsPerEntry(context)
§function

runDtsPrePass(context: BuildContext, monitor?: MemoryMonitor): Promise<void>

Runs the d.ts pre-pass: for each bundled dep, produces _dependencies/<dep>/index.d.ts by running rollup-plugin-dts over the dep's types entry. Cross-dep type imports are marked external so the per-entry d.ts pass can route them through _dependencies/.

Parameters

NameTypeDescription
§context
BuildContext
Resolved build context.
§monitor?
MemoryMonitor
Optional memory monitor invoked between jobs.

Example

Producing _dependencies/<dep>/index.d.ts for a self-contained build

await runDtsPrePass(context)

Interfaces

§interface

GenerateDeclarationsResult

Result of running tsc to emit declaration files.

Properties

§stderr:string
Captured stderr content from tsc.
§stdout:string
Captured stdout content from tsc.
§success:boolean
Whether the tsc invocation succeeded.
§interface

SiblingEntry

Sibling entry record consumed by createSiblingExternalizePlugin.
Each sibling represents another entry-point in the same library that has its own bundled index.d.ts. The per-entry d.ts pass externalizes imports that resolve into a sibling's directory so consumers see one canonical type surface (e.g., import type { EntryPoint } from '../models' instead of an inlined declaration in every entry).

Properties

§indexDtsPath:string
Absolute path to the entry's bundled index.d.ts.
§srcPath:string
Entry's srcPath (subpath under <outputPath>). '' for the package root.
§interface

SiblingResolverInput

Inputs to createSiblingExternalizePlugin.

Properties

§selfDtsPath:string
Absolute path to the current entry's bundled index.d.ts.
§selfSrcPath:string
srcPath of the entry the plugin is rewriting.
§siblings:SiblingEntry[]
Other entries' bundled index.d.ts records.