Skip to content

Clean up rlc-common debt and decouple modular generation in typespec-ts#4726

Merged
xirzec merged 16 commits into
mainfrom
xirzec-typespec-ts-cleanup
Jun 29, 2026
Merged

Clean up rlc-common debt and decouple modular generation in typespec-ts#4726
xirzec merged 16 commits into
mainfrom
xirzec-typespec-ts-cleanup

Conversation

@xirzec

@xirzec xirzec commented Jun 26, 2026

Copy link
Copy Markdown
Member

What & why

The typespec-ts emitter still carried a large amount of vestigial debt from the now-defunct RLC (Rest Level Client) generator, even though it only emits Modular clients today. This PR pays that debt down and refreshes the docs. The work is internal/refactor + docs only — no change to generated output (proven via check:tree, see below).

Works toward and closes Azure/autorest.typescript#2726.

Changes

rlc-common cleanup

  • Remove dead rlc-common code (static helpers, karma config) and relocate the live code into logical homes in the main source tree; move the associated unit tests to mirror the new layout.

De-RLC naming

  • Rename public and internal RLC-era types/functions (e.g. RLCModelClientModel), discriminants, context keys, and comments — src is now free of rlc/RLC tokens.
  • Rename ModularClientOptionsClientModuleInfo (+ getModularClientOptionsgetClientModuleInfo): it's a per-sub-client path/name descriptor, unrelated to the ClientOptions resolved-options bag despite the old name.

Structural decoupling (Azure/autorest.typescript#2726)

  • Decouple the client code model build from modular source generation: buildClientCodeModels is now a pure function owned by metadata generation, and the hidden generateSample ordering side-effect was relocated.
  • Collapse the always-identical modularSourcesDir into sourcesDir.
  • Elide the redundant modular qualifier from index.ts-local names now that modular is the only mode (shared Modular* types intentionally kept — dropping "modular" there would collide with EmitterOptions/ClientOptions).

Dead option removal

  • Remove the vestigial compatibility-query-multi-format emitter option. It only ever influenced the transform/client-code-model (RLC lineage) path and was never consulted by modular serialization; its default was false, so removal is output-neutral.

Docs

  • Rewrite CONTRIBUTING.md for current reality (correct repo URL + submodule init, real vitest projects/scripts, the spector generate → check:tree pipeline, valid debug profile).
  • Fix RLC-era wording in README.md and drop the stale "experimental" framing from the README tagline and package.json description.

Verification

  • pnpm build ✓, pnpm lint (--max-warnings=0) ✓
  • pnpm test-next (244) ✓, pnpm unit-test (657) ✓
  • Full baseline gate — copy:typespecgenerate-tsp-onlycheck:tree — passes with a clean tree, proving zero generated-output drift across all the refactors.

xirzec and others added 13 commits June 26, 2026 15:30
The static/ helpers (paginate-content, polling-content, serialize-helper, sample-template) and the Karma config builder are leftovers from the removed RLC generator. They are not imported or invoked anywhere in the Modular emit path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the former rlc-common module's live code out of the vestigial rlc-common/ folder: naming/model helpers to src/utils, the client model interfaces to src/interfaces.ts, and the metadata/test scaffolding builders to src/metadata. Drop the barrel; callers import from the new homes directly. No symbol renames or behavior change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Relocate the former test-next/unit/rlc-common tests alongside the code they exercise: helper tests to test-next/unit/utils and metadata/test builder tests to test-next/unit/metadata.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pass 2)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The client code model is only consumed by metadata generation, not by modular source generation. Move buildClientCodeModels() to be owned by generateMetadataAndTest(), make it a pure function, and relocate the generateSample baseline reset out of transformClientModel() so the two phases no longer have a hidden ordering dependency. Also removes the dead serviceNameToClientModelsMap/needUnexpectedHelper maps.

Works toward Azure/autorest.typescript#2726.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GenerationDirDetail carried both sourcesDir and modularSourcesDir, which were always assigned the same value - a leftover from when RLC and modular emitted to separate directories. Unify on a single sourcesDir field.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Modular is the only generation mode, so the qualifier added no signal on
index.ts-local names. Renames generateModularSources -> generateSources and
modularSourcesRoot -> sourcesRoot, and drops the vestigial "for modular
packages" framing from a comment. Shared Modular* types are intentionally
left untouched: dropping "modular" there would collide with EmitterOptions
and ClientOptions, which are genuinely distinct concepts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The type carries a per-sub-client path/name descriptor (subfolder,
clientName) and is unrelated to the ClientOptions resolved-options bag
despite the similar name. Rename it and its producer
getModularClientOptions -> getClientModuleInfo (and the local var) so the
name reflects what it actually models.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The old guide predated the move into typespec-azure and described the
defunct RLC generator: wrong clone URL, nonexistent test suites/scripts,
dead start-test-server/smoke-test flows, and VS Code launch profiles that
no longer exist. Rewrite it around the actual monorepo setup (submodule
init, pnpm filtered build), the three vitest projects, the spector
generate -> check:tree pipeline, and the real Debug Current Test File
profile.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
README documented an option as applying "in RLC"; lib.ts already dropped
that qualifier, so align the README. Also remove the stale "experimental"
descriptor from the README tagline and the package.json description -- this
is the production Azure TypeScript emitter, not an experiment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This option only ever influenced the transform/client-code-model (RLC
lineage) serialization path -- it was read solely by getSpecialSerializeInfo
and getParameterSerializationInfo, both reached only from transform/*. The
modular query-collection serialization goes through getCollectionFormatHelper,
which never consulted the flag. With RLC output gone the option is dead, and
no spec/SDK repo sets it.

Remove the option (lib.ts interface + schema, ClientOptions field) and the
now-dead branches. Its default was false, so getHasMultiCollection collapses
to header-only multi and the parameter-utils union fallback drops -- both
identical to prior default behavior, making this output-neutral.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-sdk-automation

Copy link
Copy Markdown

All changed packages have been documented.

  • @azure-tools/typespec-ts
Show changes

@azure-tools/typespec-ts - internal ✏️

Clean up vestigial RLC technical debt in the emitter now that only Modular generation is supported: remove the dead rlc-common subfolder and relocate its live code into the main source tree, de-RLC internal type/function names (for example RLCModel -> ClientModel, ModularClientOptions -> ClientModuleInfo), decouple the client code model build from source generation, collapse the redundant modularSourcesDir, remove the dead compatibility-query-multi-format emitter option, and refresh the README and CONTRIBUTING docs. No changes to the generated output.

@pkg-pr-new

pkg-pr-new Bot commented Jun 26, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-ts@4726

commit: 50fd982

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

⚡ Benchmark Results

⚠️ 5 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
linter 🟢 131.3ms 🟢 139.3ms +6.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🟡 17.9ms 🟡 19.0ms +6.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 20.9ms 🔴 22.4ms +7.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 4.4ms 🟢 5.6ms +27.5% 🔴
 ↳ emit/@typespec/openapi3/write 🟢 17.3ms 🟢 20.9ms +20.7% 🔴
Full details – comparing 29a6956 vs baseline d1e5c84
Metric Baseline Current Change
total 🔴 604.5ms 🔴 605.8ms +0.2%
loader 🟢 193.4ms 🟢 178.8ms -7.5% 🟢
resolver 🟢 18.7ms 🟢 18.2ms -2.8%
checker 🟢 186.1ms 🟢 187.0ms +0.5%
validation 🟢 44.9ms 🟢 44.2ms -1.7%
 ↳ validation/@azure-tools/typespec-azure-core 🟢 6.5ms 🟢 6.4ms -2.5%
 ↳ validation/@typespec/http 🟢 5.4ms 🟢 5.4ms +0.8%
 ↳ validation/@typespec/rest 🟢 0.6ms 🟢 0.6ms -0.8%
 ↳ validation/@typespec/versioning 🔴 30.7ms 🔴 29.3ms -4.6%
 ↳ validation/compiler 🟢 1.7ms 🟢 1.7ms +0.2%
linter 🟢 131.3ms 🟢 139.3ms +6.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.0ms 🟢 0.0ms +5.6%
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.2ms 🟢 0.2ms +4.5%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 5.9ms 🟢 5.7ms -3.3%
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 0.6ms 🟢 0.6ms -2.5%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.1ms 🟢 0.1ms +13.0%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 0.8ms 🟢 0.9ms +0.3%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 0.6ms 🟢 0.6ms -1.9%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.2ms 🟢 0.2ms +3.4%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.3ms 🟢 0.3ms +15.4%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.3ms 🟢 0.3ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.2ms 🟢 0.2ms +2.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 0.3ms 🟢 0.3ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.0ms 🟢 0.0ms +8.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.1ms 🟢 0.1ms +2.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.1ms 🟢 0.1ms +7.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.5ms 🟢 0.5ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.4ms 🟢 0.4ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🟡 17.9ms 🟡 19.0ms +6.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 1.2ms 🟢 1.2ms -1.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.1ms 🟢 0.1ms +2.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.2ms 🟢 0.3ms +7.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 1.2ms 🟢 1.2ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 1.9ms 🟢 2.1ms +10.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 2.0ms 🟢 2.0ms -0.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🟡 19.6ms 🟡 19.3ms -1.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 24.0ms 🔴 23.5ms -1.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.0ms 🟢 0.0ms +1.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 4.9ms 🟢 5.6ms +15.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.2ms 🟢 0.2ms -1.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.0ms 🟢 0.0ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.2ms 🟢 0.2ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.4ms 🟢 0.3ms -0.9%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.2ms 🟢 0.2ms -5.3%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.3ms 🟢 0.3ms -6.8%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.0ms 🟢 0.0ms -6.4%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 20.9ms 🔴 22.4ms +7.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.3ms 🟢 0.3ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.3ms 🟢 0.3ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 4.7ms 🟢 5.6ms +18.1%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.1ms 🟢 0.1ms +2.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🟢 4.1ms 🟢 4.3ms +7.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-lifecycle-operations 🟢 0.0ms 🟢 0.0ms +13.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟢 4.0ms 🟢 4.4ms +9.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.1ms 🟢 0.1ms -2.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.1ms 🟢 0.1ms +3.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 1.0ms 🟢 1.7ms +71.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟢 4.3ms 🟢 5.0ms +17.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.4ms 🟢 0.3ms -3.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 0.4ms 🟢 0.5ms +7.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.2ms 🟢 0.2ms +5.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.1ms 🟢 0.1ms +5.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.0ms 🟢 0.0ms +25.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.1ms 🟢 0.1ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.1ms 🟢 0.1ms +6.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.0ms 🟢 0.0ms +1.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.2ms 🟢 0.2ms +2.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.0ms 🟢 0.0ms -0.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.2ms 🟢 0.2ms +9.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 4.4ms 🟢 5.6ms +27.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.3ms 🟢 0.3ms +7.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.2ms 🟢 0.2ms +8.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.1ms 🟢 0.1ms +7.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.1ms 🟢 0.1ms +5.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.2ms 🟢 0.2ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.0ms 🟢 0.0ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟡 15.1ms 🟡 13.3ms -12.1% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.0ms 🟢 0.0ms -1.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 0.3ms 🟢 0.3ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.1ms 🟢 0.1ms +9.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-override-props 🟢 0.1ms 🟢 0.1ms -6.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.2ms 🟢 0.2ms +11.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🟡 19.6ms 🟡 19.7ms +0.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.1ms 🟢 0.2ms +11.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.2ms 🟢 0.1ms -2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 2.4ms 🟢 2.8ms +18.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.4ms 🟢 0.4ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.0ms 🟢 0.0ms +1.3%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 1.1ms 🟢 1.3ms +19.4%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 0.2ms 🟢 0.2ms -5.0%
emit 🔴 5.50s 🔴 5.48s -0.3%
 ↳ emit/@azure-tools/typespec-autorest 🟢 158.4ms 🟢 159.4ms +0.6%
 ↳ emit/@azure-tools/typespec-python 🔴 4.17s 🔴 4.18s +0.1%
 ↳ emit/@typespec/http-client-js 🔴 1.02s 🔴 953.1ms -6.2% 🟢
 ↳ emit/@typespec/openapi3 🟢 145.0ms 🟢 145.3ms +0.2%
 ↳ emit/@typespec/openapi3/compute 🟢 127.3ms 🟢 124.2ms -2.4%
 ↳ emit/@typespec/openapi3/write 🟢 17.3ms 🟢 20.9ms +20.7% 🔴

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

@azure-sdk-automation

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website

xirzec and others added 2 commits June 26, 2026 20:49
Run prettier --write across files touched by the rlc-common cleanup and
de-RLC rename passes. The relocation appended/modified imports that
prettier's import-sort plugin reorders and re-wraps; this brings them in
line so `prettier . --check` (CI format job) passes. Formatting-only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run `pnpm regen-docs` so the website reference reflects the removed
`compatibility-query-multi-format` emitter option and the dropped
"experimental" framing in the emitter description. The Website CI job
regenerates these docs during validation and fails on any drift.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the meta:website TypeSpec.io updates label Jun 27, 2026
Resolves the rename+modify conflict GitHub flagged: main's
`use-tslib-catalog-monorepo` fix edited build-azure-monorepo-package.ts at
its old src/rlc-common/... path, while this branch relocated that file to
src/metadata/package-json/. Git rename detection carried main's
`tslib: "catalog:"` change into the relocated file. Also picks up the core
submodule bump (ae88584 -> 924435b) and main's changeset.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@xirzec xirzec added this pull request to the merge queue Jun 29, 2026
Merged via the queue into main with commit d1c08a7 Jun 29, 2026
31 checks passed
@xirzec xirzec deleted the xirzec-typespec-ts-cleanup branch June 29, 2026 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:typescript Issues for @azure-tools/typespec-ts emitter meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decouple modular generator from RLC logic

2 participants