fix(compiler): resolve emitter options for subpath exports - #11746
fix(compiler): resolve emitter options for subpath exports#11746Tanvir Alam (tanvir-ux) wants to merge 4 commits into
Conversation
|
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. |
There was a problem hiding this comment.
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 tometadata.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.
| if (emitterOutputDir === undefined) { | ||
| emitterOutputDir = [options.outputDir, metadata.name].filter(isDefined).join("/"); | ||
| } |
| let { "emitter-output-dir": emitterOutputDir, ...emitterOptions } = | ||
| emittersOptions[metadata.name ?? emitterNameOrPath] ?? {}; | ||
| emittersOptions[emitterNameOrPath] ?? | ||
| (metadata.name !== undefined ? emittersOptions[metadata.name] : undefined) ?? | ||
| {}; |
|
@microsoft-github-policy-service agree |
There was a problem hiding this comment.
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
emitterOutputDiris still derived frommetadata.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 setemitter-output-dir. Consider using the emit specifier for module emitters to avoid collisions.
if (emitterOutputDir === undefined) {
emitterOutputDir = [options.outputDir, metadata.name].filter(isDefined).join("/");
}
| // 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; |
commit: |
|
All changed packages have been documented.
Show changes
|
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.
f3b62bd to
2053239
Compare
| // name for module emitters) for older configs and file-based emitters. | ||
| const libraryName = metadata.name; | ||
| let emitterOptionsKey = emitterNameOrPath; | ||
| if ( |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
loadEmitter()looked up tspconfig options withmetadata.namefrom the parentpackage.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