feat(angular): DI-based runtime base-URL composition via override.angular.baseUrl - #3711
feat(angular): DI-based runtime base-URL composition via override.angular.baseUrl#3711the-ult wants to merge 3 commits into
Conversation
…ular.baseUrl (orval-labs#3702) Opt-in per-output base-URL InjectionToken with a factory default, a per-output resolver token, provide<Api>BaseUrl/provide<Api>BaseUrlResolver helpers, and a normalizeBaseUrl join helper — all emitted code, no runtime package. Resolution precedence is pure DI: direct token provider > provided resolver > default resolver > embedded OpenAPI server URL. HttpClient services inject the token as a class field; httpResource functions resolve it injector-aware (options.injector supported). The prefix is applied after makeRouteSafe so it is never URL-encoded, apiId is explicit and validated, and the option is mutually exclusive with output.baseUrl. Output is byte-identical when the option is not set. Fixes orval-labs#3702 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds configurable Angular DI-based runtime base URL composition with generated tokens, resolver/provider helpers, HttpClient and ChangesAngular base URL composition
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant GeneratedClient
participant AngularToken as PETSTORE_BASE_URL
participant Resolver as PETSTORE_BASE_URL_RESOLVER
participant HttpTransport
GeneratedClient->>AngularToken: Resolve injected base URL
AngularToken->>Resolver: Resolve apiId and serverUrl context
Resolver-->>AngularToken: Return selected runtime URL
AngularToken-->>GeneratedClient: Return normalized base URL
GeneratedClient->>HttpTransport: Send request with prefixed route
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR adds an opt-in Angular DI-based runtime base-URL composition feature via override.angular.baseUrl, generating a per-output <target>.base-url.ts module that exports API-specific InjectionTokens, resolver/provider helpers, and a base-URL normalization helper, and wiring generated Angular HttpClient services and httpResource functions to consume the composed base URL.
Changes:
- Introduces
override.angular.baseUrloption normalization/validation (including warnings/errors) and new core types. - Adds Angular generator support to emit and consume a generated DI base-URL token file across
httpClient,httpResource, andbothmodes. - Adds extensive tests, snapshots, sample Angular app coverage, and documentation for the new DI base-URL mechanism.
Reviewed changes
Copilot reviewed 130 out of 130 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/configs/angular.config.ts | Adds new test configs for base-url token outputs across modes. |
| tests/snapshots/angular/base-url-token/endpoints.base-url.ts | Snapshot of generated base-url DI token module (non-zod). |
| tests/snapshots/angular/base-url-token/model/cat.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/catType.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/createPetsBody.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/createPetsParams.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/createPetsSort.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/dachshund.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/dachshundBreed.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/dog.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/dogType.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/error.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/index.ts | Snapshot barrel for base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/labradoodle.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/labradoodleBreed.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/listPetsParams.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/listPetsSort.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/pet.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/petCallingCode.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/petCountry.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/pets.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token/model/petWithTag.ts | Snapshot fixture for new base-url-token test output models. |
| tests/snapshots/angular/base-url-token-zod/endpoints.base-url.ts | Snapshot of generated base-url DI token module (zod mode). |
| tests/snapshots/angular/base-url-token-zod/model/cat.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/createPetsBody.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/createPetsHeaders.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/createPetsParams.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/dachshund.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/dog.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/error.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/index.ts | Snapshot barrel for base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/labradoodle.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/listPetsHeaders.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/listPetsParams.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/pet.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/petWithTag.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-zod/model/pets.zod.ts | Snapshot fixture for new base-url-token zod models. |
| tests/snapshots/angular/base-url-token-http-resource/endpoints.ts | Snapshot of generated httpResource output consuming DI baseUrl token. |
| tests/snapshots/angular/base-url-token-http-resource/endpoints.base-url.ts | Snapshot of generated base-url DI token module for httpResource output. |
| tests/snapshots/angular/base-url-token-http-resource/model/cat.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/catType.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/createPetsBody.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/createPetsParams.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/createPetsSort.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/dachshund.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/dachshundBreed.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/dog.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/dogType.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/error.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/index.ts | Snapshot barrel for base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/labradoodle.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/labradoodleBreed.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/listPetsParams.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/listPetsSort.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/pet.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/petCallingCode.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/petCountry.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/pets.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-http-resource/model/petWithTag.ts | Snapshot fixture for new base-url-token-http-resource models. |
| tests/snapshots/angular/base-url-token-both/endpoints.base-url.ts | Snapshot of base-url DI token module for both mode. |
| tests/snapshots/angular/base-url-token-both/health/health.service.ts | Snapshot of tag-split HttpClient service consuming DI baseUrl token. |
| tests/snapshots/angular/base-url-token-both/health/health.resource.ts | Snapshot of tag-split httpResource functions consuming DI baseUrl token. |
| tests/snapshots/angular/base-url-token-both/pets/pets.service.ts | Snapshot of tag-split HttpClient service consuming DI baseUrl token. |
| tests/snapshots/angular/base-url-token-both/pets/pets.resource.ts | Snapshot of tag-split httpResource functions consuming DI baseUrl token. |
| tests/snapshots/angular/base-url-token-both/model/cat.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/catType.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/createPetsBody.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/createPetsParams.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/createPetsSort.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/dachshund.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/dachshundBreed.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/dog.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/dogType.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/error.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/index.ts | Snapshot barrel for base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/labradoodle.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/labradoodleBreed.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/listPetsParams.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/listPetsSort.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/pet.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/petCallingCode.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/petCountry.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/pets.ts | Snapshot fixture for new base-url-token-both models. |
| tests/snapshots/angular/base-url-token-both/model/petWithTag.ts | Snapshot fixture for new base-url-token-both models. |
| samples/angular-app/orval.config.ts | Adds a sample-app Orval target exercising the base-url DI option. |
| samples/angular-app/src/app/base-url-token.spec.ts | Adds end-to-end TestBed coverage for base-url DI precedence and usage. |
| samples/angular-app/src/api/base-url-token/petstore.base-url.ts | Sample generated base-url DI token module. |
| samples/angular-app/src/api/base-url-token/pets/pets.resource.ts | Sample generated httpResource functions consuming DI baseUrl token. |
| samples/angular-app/src/api/base-url-token/model/createPetsBody.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/createPetsBodyStatus.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/error.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/index.ts | Sample generated model barrel for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/listPetsParams.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/pet.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/petStatus.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/pets.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/searchPetsParams.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/src/api/base-url-token/model/searchPetsStatus.ts | Sample generated model fixtures for base-url token sample. |
| samples/angular-app/snapshots/api/base-url-token/petstore.base-url.ts | Snapshot coverage for sample generated base-url DI token module. |
| samples/angular-app/snapshots/api/base-url-token/pets/pets.resource.ts | Snapshot coverage for sample generated httpResource code with DI baseUrl. |
| samples/angular-app/snapshots/api/base-url-token/model/createPetsBody.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/createPetsBodyStatus.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/error.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/index.ts | Snapshot coverage for sample generated model barrel. |
| samples/angular-app/snapshots/api/base-url-token/model/listPetsParams.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/pet.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/petStatus.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/pets.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/searchPetsParams.ts | Snapshot coverage for sample generated models. |
| samples/angular-app/snapshots/api/base-url-token/model/searchPetsStatus.ts | Snapshot coverage for sample generated models. |
| packages/core/src/types.ts | Adds AngularBaseUrlOptions and wires it into Angular override option types. |
| packages/core/src/getters/route.ts | Extracts servers URL resolution into reusable resolveServerUrl. |
| packages/orval/src/utils/options.ts | Adds config normalization/validation for override.angular.baseUrl. |
| packages/orval/src/utils/options.test.ts | Adds unit tests for override.angular.baseUrl normalization behavior. |
| packages/angular/src/base-url.ts | Implements base-url DI token extra-file generation and naming helpers. |
| packages/angular/src/base-url.test.ts | Adds unit tests for base-url extra file content, naming, and server resolution. |
| packages/angular/src/http-client.ts | Prefixes generated routes with injected baseUrl token when configured. |
| packages/angular/src/http-client.test.ts | Adds tests for base-url token integration in HttpClient generator path. |
| packages/angular/src/http-resource.ts | Prefixes generated routes with injected baseUrl token when configured. |
| packages/angular/src/http-resource.test.ts | Adds tests for base-url token integration in httpResource generator path. |
| packages/angular/src/utils.ts | Supports optional injected baseUrl class field in generated service shells. |
| packages/angular/src/constants.ts | Ensures required Angular core imports support new injection usage patterns. |
| packages/angular/src/index.ts | Wires base-url extra files into Angular generator builders and exports helpers. |
| packages/angular/src/index.test.ts | Updates builder expectations (extraFiles always present, no-op when unset). |
| docs/content/docs/reference/configuration/output.mdx | Documents override.angular.baseUrl option and its constraints. |
| docs/content/docs/guides/angular.mdx | Adds Angular guide section explaining DI-based base URL composition and usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (outputBaseUrl) { | ||
| throw new Error( | ||
| styleText( | ||
| 'red', | ||
| "`override.angular.baseUrl` cannot be combined with the top-level `output.baseUrl`. Remove `output.baseUrl` — the base-URL token's server-URL fallback is resolved from the specification's `servers` field, or provide a custom resolver via the generated `provide<Api>BaseUrlResolver` helper.", | ||
| ), | ||
| ); | ||
| } |
Copilot review: the mutual-exclusivity guard against output.baseUrl was truthiness-based, so an explicitly configured empty-string baseUrl slipped through. The check is now '!== undefined', with a regression test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Copilot review triage:
|
@orval/angular
@orval/axios
@orval/core
@orval/effect
@orval/fetch
@orval/hono
@orval/mcp
@orval/mock
orval
@orval/query
@orval/solid-start
@orval/swr
@orval/zod
commit: |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
packages/angular/src/http-client.ts (1)
27-30: 📐 Maintainability & Code Quality | 🔵 TrivialDuplicate class-open template instead of reusing
buildServiceClassOpen.
generateAngularHeaderhand-rolls the@Injectable ... export class { private readonly http = inject(HttpClient); ... }shell inline, duplicating the logic thatbuildServiceClassOpen(inutils.ts) already encapsulates — including, now, the newbaseUrlfield injection.http-resource.ts'sgenerateHttpResourceHeadercallsbuildServiceClassOpenwith abaseUrlFieldInitializer; this file re-implements the same feature by hand instead. Two independent implementations of the same feature increase drift risk (a future change to one is easy to forget in the other).♻️ Suggested direction
Consider extending
buildServiceClassOpento also emit theHTTP_CLIENT_OPTIONS_TEMPLATE/observe-options/accept-helpers preamble (or extracting just the class-open fragment) sogenerateAngularHeadercan call it instead of duplicating the@Injectable/class-open block.Also applies to: 225-270
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/angular/src/http-client.ts` around lines 27 - 30, Refactor generateAngularHeader to reuse buildServiceClassOpen for the Injectable/class-open shell instead of assembling it inline. Extend or adapt buildServiceClassOpen to emit the required HTTP client options and helper preamble while preserving the baseUrlFieldInitializer behavior used by generateHttpResourceHeader, then remove the duplicated class-opening logic from generateAngularHeader.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/core/src/getters/route.ts`:
- Line 94: Update the variable lookup condition in the route getter to check
whether variables[variableKey] is not undefined rather than relying on
truthiness. Preserve explicitly provided empty-string values and only fall back
to variable.default when the value is absent.
In `@samples/angular-app/src/api/base-url-token/pets/pets.resource.ts`:
- Around line 178-182: Update listPetsResource and showPetByIdResource so
request construction and all reads of params, petId, and version occur inside
the reactive callback passed to httpResource. Match the existing pattern in
searchPetsResource, showPetTextResource, and downloadFileResource, ensuring
later signal changes recompute the URL and query parameters.
- Around line 139-145: Update the filterParams call in the pets resource to pass
true as its third argument, preserving explicit null values for the required
nullable fields in SearchPetsParams while keeping the existing parameter object
and required-field set unchanged.
---
Nitpick comments:
In `@packages/angular/src/http-client.ts`:
- Around line 27-30: Refactor generateAngularHeader to reuse
buildServiceClassOpen for the Injectable/class-open shell instead of assembling
it inline. Extend or adapt buildServiceClassOpen to emit the required HTTP
client options and helper preamble while preserving the baseUrlFieldInitializer
behavior used by generateHttpResourceHeader, then remove the duplicated
class-opening logic from generateAngularHeader.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 473c868d-1e73-4eb6-98da-2244864ef5c7
⛔ Files ignored due to path filters (98)
samples/angular-app/__snapshots__/api/base-url-token/model/createPetsBody.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/createPetsBodyStatus.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/error.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/index.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/listPetsParams.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/pet.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/petStatus.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/pets.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/searchPetsParams.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/model/searchPetsStatus.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/pets/pets.resource.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/pets/pets.service.tsis excluded by!**/__snapshots__/**samples/angular-app/__snapshots__/api/base-url-token/petstore.base-url.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/endpoints.base-url.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/health/health.resource.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/health/health.service.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/cat.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/catType.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/createPetsBody.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/createPetsParams.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/createPetsSort.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/dachshund.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/dachshundBreed.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/dog.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/dogType.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/error.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/index.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/labradoodle.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/labradoodleBreed.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/listPetsParams.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/listPetsSort.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/pet.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/petCallingCode.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/petCountry.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/petWithTag.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/model/pets.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/pets/pets.resource.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-both/pets/pets.service.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/endpoints.base-url.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/endpoints.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/cat.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/catType.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/createPetsBody.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/createPetsParams.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/createPetsSort.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/dachshund.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/dachshundBreed.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/dog.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/dogType.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/error.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/index.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/labradoodle.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/labradoodleBreed.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/listPetsParams.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/listPetsSort.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/pet.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/petCallingCode.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/petCountry.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/petWithTag.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-http-resource/model/pets.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/endpoints.base-url.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/endpoints.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/cat.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/createPetsBody.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/createPetsHeaders.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/createPetsParams.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/dachshund.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/dog.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/error.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/index.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/labradoodle.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/listPetsHeaders.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/listPetsParams.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/pet.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/petWithTag.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token-zod/model/pets.zod.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/endpoints.base-url.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/endpoints.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/cat.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/catType.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/createPetsBody.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/createPetsParams.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/createPetsSort.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/dachshund.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/dachshundBreed.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/dog.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/dogType.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/error.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/index.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/labradoodle.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/labradoodleBreed.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/listPetsParams.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/listPetsSort.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/pet.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/petCallingCode.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/petCountry.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/petWithTag.tsis excluded by!**/__snapshots__/**tests/__snapshots__/angular/base-url-token/model/pets.tsis excluded by!**/__snapshots__/**
📒 Files selected for processing (32)
docs/content/docs/guides/angular.mdxdocs/content/docs/reference/configuration/output.mdxpackages/angular/src/base-url.test.tspackages/angular/src/base-url.tspackages/angular/src/constants.tspackages/angular/src/http-client.test.tspackages/angular/src/http-client.tspackages/angular/src/http-resource.test.tspackages/angular/src/http-resource.tspackages/angular/src/index.test.tspackages/angular/src/index.tspackages/angular/src/utils.tspackages/core/src/getters/route.tspackages/core/src/types.tspackages/orval/src/utils/options.test.tspackages/orval/src/utils/options.tssamples/angular-app/orval.config.tssamples/angular-app/src/api/base-url-token/model/createPetsBody.tssamples/angular-app/src/api/base-url-token/model/createPetsBodyStatus.tssamples/angular-app/src/api/base-url-token/model/error.tssamples/angular-app/src/api/base-url-token/model/index.tssamples/angular-app/src/api/base-url-token/model/listPetsParams.tssamples/angular-app/src/api/base-url-token/model/pet.tssamples/angular-app/src/api/base-url-token/model/petStatus.tssamples/angular-app/src/api/base-url-token/model/pets.tssamples/angular-app/src/api/base-url-token/model/searchPetsParams.tssamples/angular-app/src/api/base-url-token/model/searchPetsStatus.tssamples/angular-app/src/api/base-url-token/pets/pets.resource.tssamples/angular-app/src/api/base-url-token/pets/pets.service.tssamples/angular-app/src/api/base-url-token/petstore.base-url.tssamples/angular-app/src/app/base-url-token.spec.tstests/configs/angular.config.ts
| const variables = options.variables; | ||
| for (const variableKey of Object.keys(server.variables)) { | ||
| const variable = server.variables[variableKey]; | ||
| if (variables?.[variableKey]) { |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Empty-string variable values silently fall back to defaults.
if (variables?.[variableKey]) treats an explicitly provided empty string ('') as falsy, causing it to fall through to variable.default on line 105. A user who intentionally sets variables: { basePath: '' } (e.g., to remove a path prefix) would have their value ignored. Use !== undefined instead of truthiness:
- if (variables?.[variableKey]) {
+ if (variables?.[variableKey] !== undefined) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (variables?.[variableKey]) { | |
| if (variables?.[variableKey] !== undefined) { |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/core/src/getters/route.ts` at line 94, Update the variable lookup
condition in the route getter to check whether variables[variableKey] is not
undefined rather than relying on truthiness. Preserve explicitly provided
empty-string values and only fall back to variable.default when the value is
absent.
| params: filterParams( | ||
| params?.() ?? {}, | ||
| new Set<string>([ | ||
| 'requirednullableString', | ||
| 'requirednullableStringTwo', | ||
| ]), | ||
| ), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Preserve required nullable query parameters.
SearchPetsParams declares required nullable fields, but this call omits the preserveRequiredNullables argument. As a result, explicit null values are filtered out despite the fields being required. Pass true as the third argument so the generated request preserves them.
Proposed fix
params: filterParams(
params?.() ?? {},
new Set<string>([
'requirednullableString',
'requirednullableStringTwo',
]),
+ true,
),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| params: filterParams( | |
| params?.() ?? {}, | |
| new Set<string>([ | |
| 'requirednullableString', | |
| 'requirednullableStringTwo', | |
| ]), | |
| ), | |
| params: filterParams( | |
| params?.() ?? {}, | |
| new Set<string>([ | |
| 'requirednullableString', | |
| 'requirednullableStringTwo', | |
| ]), | |
| true, | |
| ), |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@samples/angular-app/src/api/base-url-token/pets/pets.resource.ts` around
lines 139 - 145, Update the filterParams call in the pets resource to pass true
as its third argument, preserving explicit null values for the required nullable
fields in SearchPetsParams while keeping the existing parameter object and
required-field set unchanged.
| const request = { | ||
| url: `${baseUrl}/v${version?.() ?? 1}/pets`, | ||
| params: filterParams(params?.() ?? {}, new Set<string>([])), | ||
| }; | ||
| const normalizedRequest: HttpResourceRequest = request; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Keep signal reads inside the httpResource factory.
listPetsResource captures params/version, and showPetByIdResource captures petId/version, before httpResource receives its reactive callback. Later signal changes therefore do not update the request URL or query parameters. Move request construction into the callback, as already done in searchPetsResource, showPetTextResource, and downloadFileResource.
Also applies to: 250-251
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@samples/angular-app/src/api/base-url-token/pets/pets.resource.ts` around
lines 178 - 182, Update listPetsResource and showPetByIdResource so request
construction and all reads of params, petId, and version occur inside the
reactive callback passed to httpResource. Match the existing pattern in
searchPetsResource, showPetTextResource, and downloadFileResource, ensuring
later signal changes recompute the URL and query parameters.
|
@the-ult looks like merge conflicts |
|
converted to draft until the merge conflicts are resolved. |
Summary
Closes #3702.
Adds opt-in Angular dependency-injection-based base-URL composition:
override.angular.baseUrl: { apiId }emits one<target>.base-url.tsfile per output containing an API-specificInjectionToken, a per-output resolver token, provide helpers, and a URL-normalization helper — so gateway/proxy routing (app/environment config) composes cleanly with the contract's server URL, scales to many generated APIs, and is overridable per injector (TestBed, SSR, second app).Generated (from the real sample output):
Resolution precedence, purely through DI (no global mutable state): direct token provider → provided resolver → default resolver → embedded OpenAPI server URL. A monorepo consuming many generated APIs registers one shared resolver function with each output's
provide<Api>BaseUrlResolver(gateway-route registry keyed by explicitapiId), and overrides a single API via itsprovide<Api>BaseUrl.Design decisions
@orval/*runtime dependency is added; generated files keep importing only@angular/*/rxjs/zod.inject()class field;httpResourcefunctions viaoptions?.injector ? options.injector.get(TOKEN) : inject(TOKEN)(httpResource already requires an injection context, so this is valid in exactly the same call sites).makeRouteSafe, so it's never URL-encoded, and custom mutators receive the composed URL. ZodruntimeValidationis orthogonal and unchanged.apiIdis required and explicit (validated/^[A-Za-z][A-Za-z0-9_-]*$/) — never derived from server URL/hostname/spec filename, per the issue.output.baseUrl(clear normalization error); warns and ignores for non-Angular clients and per-operation/per-tag placement.Backwards compatibility
100% opt-in: without
override.angular.baseUrlthe emitted output is byte-identical — verified by full regeneration showing zero modified pre-existing snapshots or sample files; only newbase-url-token*trees were added (4 new test configs: httpClient / httpResource / both+tags-split / zod+runtimeValidation, plus a CI-compiled sample-app target with 6 new TestBed specs proving injector overrides work).Verification
/tmp-symlink flake, reproduced unmodified on master)vp lint --type-aware --type-check✓ (caught and fixed a test-signature issue plain vitest missed); all 16 generated clients typecheck ✓samples/angular-app:ng build/ng lint/ng test✓ (22/22)Docs
docs/content/docs/guides/angular.mdx: "Setting the Backend URL" restructured — interceptor stays the simple single-API path; new "DI-based base URL composition (multiple APIs / gateway routing)" section with generated artifacts, precedence, gateway-registry example, TestBed override, injection-context notes, and caveats (all code copied from real generated output).docs/content/docs/reference/configuration/output.mdx:override.angular.baseUrlreference (apiIdrules,index,variables, error/warning behavior) + pointer from the top-levelbaseUrlsection.Related issues
#2581 / #3071 (runtime baseUrl prior art — this is its Angular-DI form), #3265 (fetch function injection), sibling cluster #3700, #3704, #3705, #3706. Peer precedent: OpenAPI Generator's
typescript-angularBASE_PATHtoken and ng-openapi-gen'srootUrl— a DI base-path surface is the norm for Angular OpenAPI generators.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
HttpClientservices andhttpResourceAPIs.Documentation
Bug Fixes
Tests