Support multiple namespaces in client library code generation
- Dominant language
- TypeScript
- Stars
- 27
- Forks
- 90
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 156
Description
> Migrated from https://github.com/Azure/autorest.go/issues/1452
---
## Problem
The Go code generator (`autorest.go` / `typespec-go`) currently supports generating code into a single Go package only. All types (clients, models, enums, response envelopes) are emitted to one package directory regardless of the namespace structure defined in the TypeSpec specification.
TypeSpec specifications can define multiple namespaces (e.g., for services like OpenAI where each client belongs to a different namespace, or Key Vault administration where sub-services are logically separated). Other language generators (.NET, Java, Python) are being updated to honor these namespaces. The Go generator must follow suit.
**Upstream design:** https://github.com/microsoft/typespec/issues/4537
**Detailed proposal:** https://gist.github.com/srnagar/a695faa1a4d8a5dbf44af826f05916f0
### Current behavior
- The `CodeModel` has a single root (`Module` or `ContainingModule`) with one primary package
- The TypeSpec adapter (`typespec-go/src/adapter.ts`) collapses all TypeSpec namespaces into a single `PackageContent` via `getPkg()`
- Code in `types.ts` has a comment: *"NOTE: this is temporary and will go away with namespaces"* — anticipating this work
- All clients, models, constants, and other types are placed in the same Go package
- Namespace information from TypeSpec/TCGC is ignored
### Desired behavior
TypeSpec namespaces should map to separate Go packages (subdirectories), each with its own `package` declaration. For example, a TypeSpec with namespaces `Foo` and `Bar` should generate:
```
/
├── foo/
│ ├── models.go // package foo
│ ├── client.go
│ └── ...
├── bar/
│ ├── models.go // package bar
│ ├── client.go
│ └── ...
```
### Namespace resolution priority (per cross-language proposal)
1. **`@clientNamespace` decorator** — highest priority, allows granular per-type/per-client namespace overrides
2. **`namespace` emitter option in `tspconfig.yaml`** — single root namespace for the entire library (current Azure pattern)
3. **TypeSpec namespace** — fallback to the namespaces defined in the TypeSpec source
For **unbranded** libraries, TypeSpec namespaces are used directly.
For **Azure** libraries, the emitter option and `@clientNamespace` take precedence (preserving backward compatibility with existing `tspconfig.yaml` configuration).
## Planned Changes
### 1. Code model updates (`packages/codemodel.go`)
- Extend `CodeModel` to support multiple packages as output targets (not just a single root package)
- Ensure each `SdkClientType`, `SdkModelType`, and `SdkEnumType` carries its resolved namespace so types can be assigned to the correct Go package
- Support cross-package type references (types in one package referring to types in another)
### 2. TypeSpec adapter updates (`packages/typespec-go/src`)
- Update the adapter to read namespace information from TCGC's `SdkPackage`
- TCGC now provides `.namespace` on `SdkClientType`, `SdkModelType`, and `SdkEnumType`
- TCGC provides `getNamespaceToClients()` and `getNamespaceToModels()` helper methods
- Replace the single `getPkg()` pattern with namespace-aware package resolution
- Map each distinct TypeSpec/TCGC namespace to a separate Go `Package` in the code model
- Apply namespace resolution priority: `@clientNamespace` > emitter option > TypeSpec namespace
### 3. Emitter updates (`packages/codegen.go`)
- Update `recursiveEmit()` (or equivalent) to emit multiple independent package directories
- Generate correct `package` declarations per subdirectory
- Generate proper `import` statements for cross-package references between generated packages
- Handle file naming/prefixing per package
### 4. Import and reference resolution
- When a model in package `foo` references a type in package `bar`, generate the appropriate Go import path and qualified type references (e.g., `bar.BarModel`)
- Ensure response envelopes, parameter groups, and other derived types are placed in the correct package alongside their associated client
### 5. Testing
- Add test cases for multi-namespace TypeSpec inputs
- Verify single-namespace specs continue to work unchanged (backward compatibility)
- Validate cross-package type references produce compilable Go code
## Use Cases
- **OpenAI**: Multiple clients each in their own namespace (assistants, files, messages, etc.)
- **Key Vault Administration**: Sub-services logically separated into different namespaces
- **Unbranded libraries**: Third-party specs that define their own namespace hierarchy
## Related Issues
- microsoft/typespec#4537 — cross-language design issue
- Azure/typespec-azure#1604 — TCGC namespace support (completed)
- Azure/typespec-azure#1723 — TCGC namespace implementation (completed)
- Azure/cadl-ranch#758 — scenario tests (completed)
- Azure/autorest.cpp#404 — C++ equivalent
Contributor guide
Assessment
This issue has not been assessed yet.