Skip to content

fix(compiler): resolve emitter options for subpath exports - #11746

Open
Tanvir Alam (tanvir-ux) wants to merge 4 commits into
microsoft:mainfrom
tanvir-ux:fix/subpath-emitter-options
Open

fix(compiler): resolve emitter options for subpath exports#11746
Tanvir Alam (tanvir-ux) wants to merge 4 commits into
microsoft:mainfrom
tanvir-ux:fix/subpath-emitter-options

Conversation

@tanvir-ux

Copy link
Copy Markdown

loadEmitter() looked up tspconfig options with metadata.name from the parent package.json, so emitters exposed as subpath exports (e.g. @org/pkg/typescript) never matched the key users actually wrote.

Prefer the emit specifier, then fall back to the package name so file emitters and older configs still work.

Fixes #10200

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes @typespec/compiler emitter option resolution when emitters are exposed via subpath exports (e.g. @org/pkg/typescript), by preferring the emitter specifier from tspconfig.yaml/CLI options while retaining backwards compatibility via fallback to the package/library name.

Changes:

  • Update loadEmitter() to resolve emitter options using the emit specifier first, then fall back to metadata.name.
  • Add compiler tests covering subpath-export emitters (specifier-keyed options + package-name fallback).
  • Add a Chronus changelog entry for the compiler fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/compiler/src/core/program.ts Adjusts emitter options lookup order to support subpath export specifiers.
packages/compiler/test/core/emitter-options.test.ts Adds regression tests for subpath-export emitter option resolution behavior.
.chronus/changes/fix-subpath-emitter-options-2026-8-22.md Changelog entry documenting the compiler fix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 636 to 638
if (emitterOutputDir === undefined) {
emitterOutputDir = [options.outputDir, metadata.name].filter(isDefined).join("/");
}
Comment thread packages/compiler/src/core/program.ts Outdated
Comment on lines +632 to +635
let { "emitter-output-dir": emitterOutputDir, ...emitterOptions } =
emittersOptions[metadata.name ?? emitterNameOrPath] ?? {};
emittersOptions[emitterNameOrPath] ??
(metadata.name !== undefined ? emittersOptions[metadata.name] : undefined) ??
{};
@tanvir-ux

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copilot AI review requested due to automatic review settings August 22, 2026 21:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

packages/compiler/src/core/program.ts:645

  • Default emitterOutputDir is still derived from metadata.name (package.json name for module emitters). With multiple subpath-export emitters from the same package, this can route different emitters into the same default output directory unless users explicitly set emitter-output-dir. Consider using the emit specifier for module emitters to avoid collisions.
    if (emitterOutputDir === undefined) {
      emitterOutputDir = [options.outputDir, metadata.name].filter(isDefined).join("/");
    }

Comment thread packages/compiler/src/core/program.ts Outdated
Comment on lines +630 to +634
// Prefer the specifier from tspconfig so subpath exports get matching options.
// Fall back to package.json name for file emitters and older configs.
const optionsFromSpecifier = emittersOptions[emitterNameOrPath];
const optionsFromPackageName =
metadata.name !== undefined ? emittersOptions[metadata.name] : undefined;
Copilot AI review requested due to automatic review settings August 23, 2026 19:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@pkg-pr-new

pkg-pr-new Bot commented Aug 27, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/compiler@11746

commit: 2053239

@github-actions

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/compiler
Show changes

@typespec/compiler - fix ✏️

Resolve tspconfig emitter options for packages exposed as subpath exports, and default their output directories to the emit specifier.

Prefer the tspconfig emitter specifier when looking up options so
packages exposed as subpath exports receive their configured options.

Fixes microsoft#10200
Use the emit specifier for module-emitter defaults so sibling subpath
exports do not collide, and point option schema diagnostics at the
config key that actually supplied the values.
Copilot AI review requested due to automatic review settings August 27, 2026 12:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

// name for module emitters) for older configs and file-based emitters.
const libraryName = metadata.name;
let emitterOptionsKey = emitterNameOrPath;
if (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not fully sure the solution is at the correct place here. Specially if we decide that each sub emitter will have its own $lib this seems to me like this should have already been resolved in the library loading logic

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed this is the awkward layer. computeLibraryMetadata currently always uses the package.json name for modules and ignores $lib.name (that is only used for file emitters). tspconfig options are keyed by the emit specifier, which is why I matched here.

If subpath emitters are each expected to export their own $lib with a unique name, I can move this into loadLibrary / computeLibraryMetadata so metadata.name is $lib.name (fallback package name) and loadEmitter just uses that. Want me to take it that direction, or keep the specifier-first lookup here because configs already use the emit path?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler:core Issues for @typespec/compiler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Emitter options not resolved for subpath export emitters

3 participants