feat(angular): add angular httpResource support#2923
feat(angular): add angular httpResource support#2923the-ult wants to merge 45 commits intoorval-labs:masterfrom
Conversation
Introduce a dedicated httpResource client generator with route tracking\nand resource return-type registries. Add shared dependency/templates utilities, new tests, and expose the\nangular client mode (httpClient/httpResource/both) through config\nnormalization and generator selection.
Split generated API outputs into http-client and http-resource targets\nwith updated MSW mocks and sample pages. Add routing and UI for the new httpResource screen plus the versioned\npath transformer used by both outputs.
Add lint:generated task wiring across root and tests, and update\nturbo pipeline + README guidance. Introduce ESLint configs for Angular/Next samples and refresh Angular\ncatalog + dependencies to include Angular ESLint support.
- add url-only httpResource generation and zod parse options - normalize angular runtimeValidation and update config/types/tests - document httpResource output and add zod sample pages/output
- precompute delay expressions to handle function delays safely - expand MSW tests and update angular sample mocks - expose MSW_DELAY in turbo global env
- resolve schema path when schemas is an object - avoid cleaning the wrong directory during generation
|
Initial setup to add httpResource functionality. |
There was a problem hiding this comment.
Pull request overview
Adds first-class Angular httpResource (signal-first) client generation to Orval, plus sample app and documentation updates to demonstrate HttpClient, httpResource, and httpResource + Zod flows.
Changes:
- Implement Angular
httpResourcegenerator (including “both” mode extra*.resource.tsoutput) with route/return-type registries and ResourceState helpers. - Extend config normalization + core types to support
override.angular.clientandoverride.angular.runtimeValidation, and improve schema-cleaning for object-formschemas. - Update samples/docs/tooling (Angular sample routes, generated artifacts, MSW tweaks, ESLint/turbo scripts, dependency catalogs).
Reviewed changes
Copilot reviewed 60 out of 63 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| turbo.json | Adds MSW_DELAY to global env and introduces lint:generated task. |
| tests/package.json | Adds lint:generated script for generated fixtures. |
| tests/configs/angular.config.ts | Adds Angular test outputs for httpResource + Zod (and validation-disabled) variants. |
| samples/next-app-with-fetch/package.json | Switches lint to eslint and adds flat-config dependencies. |
| samples/next-app-with-fetch/eslint.config.mjs | Adds ESLint flat config for Next sample. |
| samples/angular-query/package.json | Adds Angular ESLint + ESLint v9 toolchain deps. |
| samples/angular-query/eslint.config.mjs | Adds ESLint flat config for Angular Query sample. |
| samples/angular-query/angular.json | Adds @angular-eslint lint builder target. |
| samples/angular-app/src/orval/transformer/add-version.js | Adds OpenAPI transformer to prefix versioned routes. |
| samples/angular-app/src/orval/node.ts | Aggregates multiple generated MSW mock bundles for node tests. |
| samples/angular-app/src/orval/browser.ts | Aggregates multiple generated MSW mock bundles for browser worker. |
| samples/angular-app/src/app/http-resource.page.ts | Adds sample page demonstrating httpResource usage. |
| samples/angular-app/src/app/http-resource-zod.page.ts | Adds sample page demonstrating httpResource + Zod validation. |
| samples/angular-app/src/app/http-resource-zod.page.spec.ts | Adds basic component tests for the Zod resource page. |
| samples/angular-app/src/app/http-client.page.ts | Adds sample page demonstrating HttpClient output + content-type overloads. |
| samples/angular-app/src/app/app.ts | Refactors root component to a router-based sample navigation. |
| samples/angular-app/src/app/app.spec.ts | Updates root component test to account for router navigation links. |
| samples/angular-app/src/app/app.routes.ts | Adds routes for HttpClient / httpResource / httpResource+Zod demo pages. |
| samples/angular-app/src/app/app.config.ts | Adds router provider to standalone app config. |
| samples/angular-app/src/api/model-zod/searchPetsParams.zod.ts | Adds generated Zod schema artifacts for sample. |
| samples/angular-app/src/api/model-zod/pets.zod.ts | Adds generated Zod schema artifacts for sample. |
| samples/angular-app/src/api/model-zod/pet.zod.ts | Adds generated Zod schema artifacts for sample. |
| samples/angular-app/src/api/model-zod/listPetsParams.zod.ts | Adds generated Zod schema artifacts for sample. |
| samples/angular-app/src/api/model-zod/index.zod.ts | Adds generated Zod barrel for sample. |
| samples/angular-app/src/api/model-zod/error.zod.ts | Adds generated Zod schema artifacts for sample. |
| samples/angular-app/src/api/model-zod/createPetsBody.zod.ts | Adds generated Zod schema artifacts for sample. |
| samples/angular-app/src/api/http-resource/pets/pets.service.ts | Adds generated httpResource endpoints + mutation service + ResourceState utilities. |
| samples/angular-app/src/api/http-resource/pets/pets.msw.ts | Adds generated MSW mocks for httpResource output. |
| samples/angular-app/src/api/http-resource/index.msw.ts | Adds MSW index export for httpResource mocks. |
| samples/angular-app/src/api/http-resource-zod/pets/pets.service.ts | Adds generated httpResource endpoints with Zod parsing + service/utilities. |
| samples/angular-app/src/api/http-resource-zod/pets/pets.msw.ts | Adds generated MSW mocks for httpResource + zod output. |
| samples/angular-app/src/api/http-resource-zod/index.msw.ts | Adds MSW index export for httpResource + zod mocks. |
| samples/angular-app/src/api/http-client/pets/pets.service.ts | Updates generated HttpClient options typing (adds referrerPolicy). |
| samples/angular-app/src/api/http-client/pets/pets.msw.ts | Adds generated MSW mocks for http-client output. |
| samples/angular-app/src/api/http-client/index.msw.ts | Adds MSW index export for http-client mocks. |
| samples/angular-app/package.json | Adds Zod + ESLint toolchain updates for the Angular sample. |
| samples/angular-app/orval.config.ts | Adds multiple outputs (http-client, http-resource, http-resource-zod) + MSW mock config. |
| samples/angular-app/eslint.config.mjs | Adds ESLint flat config for Angular sample. |
| samples/angular-app/angular.json | Adds @angular-eslint lint builder target. |
| packages/orval/src/utils/options.ts | Normalizes Angular defaults for client and runtimeValidation (global + per-operation). |
| packages/orval/src/generate-spec.ts | Fixes cleaning when output.schemas is object form ({ type, path }). |
| packages/orval/src/client.ts | Plumbs normalized Angular override options into @orval/angular builder and adjusts mock typing. |
| packages/mock/src/msw/index.ts | Adjusts MSW delay expression emission (function delays now stringified + executed). |
| packages/mock/src/msw/index.test.ts | Expands MSW generator tests and updates mock option typing usage. |
| packages/core/src/types.ts | Adds Angular override types (client, runtimeValidation) and introduces NormalizedAngularOptions. |
| packages/angular/vitest.config.ts | Adds vitest config scaffold for Angular package tests. |
| packages/angular/src/utils.ts | Adds shared helpers (title generation, registries, retrieval/mutation heuristic, default content-type selection). |
| packages/angular/src/utils.test.ts | Adds tests for Angular utility helpers. |
| packages/angular/src/types.ts | Extracts reusable code templates for generated Angular client types. |
| packages/angular/src/types.test.ts | Adds conformance tests ensuring generated HttpClientOptions stays aligned with Angular API. |
| packages/angular/src/index.ts | Refactors Angular client entry to support httpClient, httpResource, and both builders. |
| packages/angular/src/index.test.ts | Adds tests ensuring builder selection behaves as expected. |
| packages/angular/src/http-resource.ts | Introduces httpResource generator with registries, parsing, factories, and extra-file support. |
| packages/angular/src/http-resource.test.ts | Adds extensive tests for httpResource generation behavior. |
| packages/angular/src/http-client.ts | Refactors HttpClient generator into its own module and shares utilities. |
| packages/angular/src/http-client.test.ts | Adds extensive tests for HttpClient generation behavior. |
| packages/angular/src/constants.ts | Centralizes Angular dependency definitions for HttpClient and httpResource modes. |
| packages/angular/README.md | Updates Angular package README formatting/content. |
| package.json | Adds root lint:generated turbo script. |
| docs/content/docs/guides/angular.mdx | Documents httpResource output and Zod runtime validation options. |
| README.md | Documents new lint scripts and updated dev workflow steps. |
| .yarnrc.yml | Updates Angular catalog versions and adds zod to catalog. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -57,10 +65,6 @@ const getGeneratorClient = ( | |||
| ? outputClient(GENERATOR_CLIENT) | |||
| : GENERATOR_CLIENT[outputClient]; | |||
|
|
|||
There was a problem hiding this comment.
getGeneratorClient no longer throws when an unknown outputClient is provided, so generator can be undefined and cause less actionable runtime errors later (e.g., when destructuring header/footer/client). Reintroduce an explicit guard that throws a clear error when the client key is not found (including the provided value).
| if (!generator) { | |
| throw new Error( | |
| `Unknown output client provided to getGeneratorClient: ${String(outputClient)}`, | |
| ); | |
| } |
| if (isResponseArrayBuffer(contentType)) return 'httpResource.arrayBuffer'; | ||
| if (isResponseBlob(contentType, response.isBlob)) return 'httpResource.blob'; |
There was a problem hiding this comment.
getHttpResourceFactory checks for application/octet-stream/PDF (arrayBuffer) before honoring response.isBlob. This can produce httpResource.arrayBuffer factories for endpoints that are modeled as Blob, leading to type/runtime mismatches in generated clients. Consider prioritizing response.isBlob (or the Blob return type) over the arrayBuffer heuristic, or otherwise ensure the factory choice and generated return type stay aligned.
| if (isResponseArrayBuffer(contentType)) return 'httpResource.arrayBuffer'; | |
| if (isResponseBlob(contentType, response.isBlob)) return 'httpResource.blob'; | |
| if (isResponseBlob(contentType, response.isBlob)) return 'httpResource.blob'; | |
| if (isResponseArrayBuffer(contentType)) return 'httpResource.arrayBuffer'; |
| export function downloadFileResource( | ||
| petId: Signal<number>, | ||
| version?: Signal<number>, | ||
| ): HttpResourceRef<Blob | undefined> { | ||
| return httpResource.arrayBuffer<Blob>( | ||
| () => `/v${version?.() ?? 1}/pet/${petId()}/downloadImage`, | ||
| ); |
There was a problem hiding this comment.
downloadFileResource returns HttpResourceRef<Blob | undefined> but uses httpResource.arrayBuffer<Blob>(...). arrayBuffer resources yield ArrayBuffer data, so this is a type/runtime mismatch. Use the blob factory for Blob responses, or change the return type to ArrayBuffer (and let consumers convert to Blob if needed).
| export function downloadFileResource( | ||
| petId: Signal<number>, | ||
| version?: Signal<number>, | ||
| ): HttpResourceRef<Blob | undefined> { | ||
| return httpResource.arrayBuffer<Blob>( | ||
| () => `/v${version?.() ?? 1}/pet/${petId()}/downloadImage`, | ||
| ); |
There was a problem hiding this comment.
downloadFileResource returns HttpResourceRef<Blob | undefined> but uses httpResource.arrayBuffer<Blob>(...). arrayBuffer resources yield ArrayBuffer data, so this is a type/runtime mismatch. Use the blob factory for Blob responses, or change the return type to ArrayBuffer (and let consumers convert to Blob if needed).
| return new HttpResponse( | ||
| overrideResponse !== undefined | ||
| ? typeof overrideResponse === 'function' | ||
| ? await overrideResponse(info) | ||
| : overrideResponse | ||
| : getShowPetByIdResponseMock(), | ||
| { status: 200, headers: { 'Content-Type': 'text/plain' } }, | ||
| ); |
There was a problem hiding this comment.
This handler sets Content-Type: text/plain but may return a Pet object (non-string) when overrideResponse is a Pet or when using the default mock. That produces an invalid/incorrect response body for a text response. Ensure the generated handler serializes non-string values appropriately (or only treats the response as text when the response body type is actually string).
| return new HttpResponse( | ||
| overrideResponse !== undefined | ||
| ? typeof overrideResponse === 'function' | ||
| ? await overrideResponse(info) | ||
| : overrideResponse | ||
| : getShowPetByIdResponseMock(), | ||
| { status: 200, headers: { 'Content-Type': 'text/plain' } }, | ||
| ); |
There was a problem hiding this comment.
This handler sets Content-Type: text/plain but may return a Pet object (non-string) when overrideResponse is a Pet or when using the default mock. That produces an invalid/incorrect response body for a text response. Ensure the generated handler serializes non-string values appropriately (or only treats the response as text when the response body type is actually string).
| return new HttpResponse( | ||
| JSON.stringify( | ||
| overrideResponse !== undefined | ||
| ? typeof overrideResponse === 'function' | ||
| ? await overrideResponse(info) | ||
| : overrideResponse | ||
| : getDownloadFileResponseMock(), | ||
| ), | ||
| { status: 200, headers: { 'Content-Type': 'application/json' } }, | ||
| ); |
There was a problem hiding this comment.
This handler JSON-stringifies a Blob response and sets Content-Type: application/json, which breaks binary downloads and does not match the declared Blob return type. The generated handler should return the Blob body directly (or use MSW’s binary helpers) and set an appropriate binary content-type (e.g., octet-stream) based on the operation’s response content-type.
| return new HttpResponse( | ||
| JSON.stringify( | ||
| overrideResponse !== undefined | ||
| ? typeof overrideResponse === 'function' | ||
| ? await overrideResponse(info) | ||
| : overrideResponse | ||
| : getDownloadFileResponseMock(), | ||
| ), | ||
| { status: 200, headers: { 'Content-Type': 'application/json' } }, | ||
| ); |
There was a problem hiding this comment.
This handler JSON-stringifies a Blob response and sets Content-Type: application/json, which breaks binary downloads and does not match the declared Blob return type. The generated handler should return the Blob body directly (or use MSW’s binary helpers) and set an appropriate binary content-type (e.g., octet-stream) based on the operation’s response content-type.
| import { | ||
| type ClientBuilder, | ||
| type ClientDependenciesBuilder, | ||
| type ClientExtraFilesBuilder, | ||
| type ClientFooterBuilder, | ||
| type ClientHeaderBuilder, | ||
| type ContextSpec, | ||
| conventionName, | ||
| generateDependencyImports, | ||
| generateFormDataAndUrlEncodedFunction, | ||
| generateMutatorImports, | ||
| generateVerbImports, | ||
| type GeneratorDependency, | ||
| type GeneratorImport, | ||
| type GeneratorMutator, | ||
| type GeneratorOptions, | ||
| type GeneratorVerbOptions, | ||
| getFileInfo, | ||
| getFullRoute, | ||
| GetterPropType, | ||
| isObject, | ||
| isSyntheticDefaultImportsAllow, | ||
| jsDoc, | ||
| type NormalizedOutputOptions, | ||
| type OpenApiInfoObject, | ||
| pascal, | ||
| type ResReqTypesValue, | ||
| toObjectString, | ||
| upath, | ||
| } from '@orval/core'; |
There was a problem hiding this comment.
Unused import generateVerbImports.
|
First absolutely stunning pr 👍 . @the-ult without me having a deeper knowledge at the moment it would be nice when you address the ai issues, (Even when you write a comment that the ai is stupid there would be fine ) |
|
Thanks :-) I wil fix/handle the CoPilot comments in the next days. |
Introduce a dedicated httpResource client generator with route tracking\nand resource return-type registries. Add shared dependency/templates utilities, new tests, and expose the\nangular client mode (httpClient/httpResource/both) through config\nnormalization and generator selection.
Split generated API outputs into http-client and http-resource targets\nwith updated MSW mocks and sample pages. Add routing and UI for the new httpResource screen plus the versioned\npath transformer used by both outputs.
Add lint:generated task wiring across root and tests, and update\nturbo pipeline + README guidance. Introduce ESLint configs for Angular/Next samples and refresh Angular\ncatalog + dependencies to include Angular ESLint support.
- add url-only httpResource generation and zod parse options - normalize angular runtimeValidation and update config/types/tests - document httpResource output and add zod sample pages/output
- precompute delay expressions to handle function delays safely - expand MSW tests and update angular sample mocks - expose MSW_DELAY in turbo global env
- resolve schema path when schemas is an object - avoid cleaning the wrong directory during generation
f7a34c9 to
ef1c58c
Compare
|
I just rebased your branch and will run the tests |
- Restore defensive guard in getGeneratorClient for custom OutputClientFunc - Fix blob/arrayBuffer check ordering in httpResource factory - Remove unused generateVerbImports import - Remove unnecessary nullish coalescing on response.definition.success - Use String.raw template literals for regex patterns - Regenerate samples with corrected blob resource output
…tp-resource' into feat/add-angular-http-resource
|
Hmm, i get the feeling this pr could be split up in to multiple pr´s. What are your thoughts @the-ult ? |
Split generated API outputs into http-client and http-resource targets\nwith updated MSW mocks and sample pages. Add routing and UI for the new httpResource screen plus the versioned\npath transformer used by both outputs.
- add url-only httpResource generation and zod parse options - normalize angular runtimeValidation and update config/types/tests - document httpResource output and add zod sample pages/output
- Restore defensive guard in getGeneratorClient for custom OutputClientFunc - Fix blob/arrayBuffer check ordering in httpResource factory - Remove unused generateVerbImports import - Remove unnecessary nullish coalescing on response.definition.success - Use String.raw template literals for regex patterns - Regenerate samples with corrected blob resource output
Revert back to not using yarn catalogs. But had to update some packages, due to yarn warnings.
Use next lint instead of eslint
revert scope creep, as much as possible
TanStack Query v5 mutation callbacks now require the extra context argument, which breaks generated Angular Query clients/tests after the catalog bump in this PR. This change updates the generator and regenerated samples to pass the 4th argument and keeps CI green in the same PR because the dependency upgrade and sample refresh already happen here.
Will be done in separate PR
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 62 out of 65 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| vi.mocked(findUp).mockImplementation((name) => { | ||
| if (name === 'pnpm-workspace.yaml') return; | ||
| if (name === '.yarnrc.yml') return; | ||
| vi.mocked(findUp).mockImplementation(async (name) => { | ||
| if (name === 'pnpm-workspace.yaml') return; | ||
| if (name === '.yarnrc.yml') return; | ||
| if (Array.isArray(name) && name.includes('package.json')) | ||
| return '/workspace/packages/app/package.json'; | ||
| return; | ||
| return; |
There was a problem hiding this comment.
This block starts a mockImplementation and then immediately starts another nested mockImplementation without closing the first one, which makes the test file syntactically invalid. Consolidate to a single findUp mock implementation (sync or async) and ensure braces/parentheses are correctly closed.
| vi.mocked(findUp).mockImplementation((name) => { | |
| if (name === 'pnpm-workspace.yaml') return; | |
| if (name === '.yarnrc.yml') return; | |
| vi.mocked(findUp).mockImplementation(async (name) => { | |
| if (name === 'pnpm-workspace.yaml') return; | |
| if (name === '.yarnrc.yml') return; | |
| if (Array.isArray(name) && name.includes('package.json')) | |
| return '/workspace/packages/app/package.json'; | |
| return; | |
| return; | |
| vi.mocked(findUp).mockImplementation(async (name) => { | |
| if (name === 'pnpm-workspace.yaml') return; | |
| if (name === '.yarnrc.yml') return; | |
| if (Array.isArray(name) && name.includes('package.json')) | |
| return '/workspace/packages/app/package.json'; | |
| return; |
packages/angular/README.md
Outdated
| <h1 align="center"> | ||
| Visit <a href="https://orval.dev" target="_blank">orval.dev</a> for docs, guides, API and beer! | ||
| </h1> | ||
|  |
There was a problem hiding this comment.
Typo in the image alt text: "Restfull" should be "Restful".
|  | |
|  |
| import { isString as isRemedaString } from 'remeda'; | ||
| import { isString as isRemedaString } from 'remeda'; |
There was a problem hiding this comment.
Duplicate import of isString as isRemedaString will cause a TypeScript compile error (duplicate identifier). Remove the extra import so it is declared only once.
| import { dynamicImport, log } from '@orval/core'; | ||
| import { dynamicImport, log } from '@orval/core'; | ||
| import { findUp, findUpMultiple } from 'find-up'; |
There was a problem hiding this comment.
Duplicate import of dynamicImport/log from @orval/core will cause a TypeScript compile error (duplicate identifier). Keep a single import statement.
| return; | ||
| }); | ||
|
|
There was a problem hiding this comment.
This mocked findUp implementation contains unreachable duplicated return; statements. Remove the extra return to avoid dead code and keep the mock implementation clear.
| return; | |
| }); | |
| }); |
| const mockPkg = { | ||
| devDependencies: { | ||
| jest: 'catalog:testing', | ||
| jest: 'catalog:ing', |
There was a problem hiding this comment.
jest is set to catalog:ing, but the test data expects a named catalog testing. As written, the resolver under test won't find a matching catalog and the assertion will fail; update the fixture to catalog:testing (or adjust the expected catalogs accordingly).
| jest: 'catalog:ing', | |
| jest: 'catalog:testing', |
| const mockPkg = { | ||
| devDependencies: { | ||
| vitest: 'catalog:testing', | ||
| vitest: 'catalog:ing', |
There was a problem hiding this comment.
vitest is set to catalog:ing, but the test data expects a named catalog testing. This will prevent the resolver from finding the catalog entry and will fail the assertion; use catalog:testing (or update the expected catalogs).
| vitest: 'catalog:ing', | |
| vitest: 'catalog:testing', |
| return new HttpResponse( | ||
| overrideResponse !== undefined | ||
| ? typeof overrideResponse === 'function' | ||
| ? await overrideResponse(info) | ||
| : overrideResponse | ||
| : getShowPetByIdResponseMock(), | ||
| { status: 200, headers: { 'Content-Type': 'text/plain' } }, | ||
| ); |
There was a problem hiding this comment.
getShowPetByIdMockHandler returns an object from getShowPetByIdResponseMock() but responds as text/plain without serialization. This is likely invalid for MSW HttpResponse; either return a string body for text/plain or serialize/use HttpResponse.json() with application/json.
| return new HttpResponse( | ||
| JSON.stringify( | ||
| overrideResponse !== undefined | ||
| ? typeof overrideResponse === 'function' | ||
| ? await overrideResponse(info) | ||
| : overrideResponse | ||
| : getDownloadFileResponseMock(), | ||
| ), | ||
| { status: 200, headers: { 'Content-Type': 'application/json' } }, | ||
| ); |
There was a problem hiding this comment.
getDownloadFileMockHandler JSON-stringifies a Blob and sets Content-Type: application/json, which won't mock a binary response correctly. Return the Blob directly and set a binary content type (or the actual file type).
|
This PR is on hold until these PR's / issues are merged: |
|
Gonna be on holiday for a week. Gonna pick this up after :-) |
Summary
This PR introduces Angular
httpResourceservice generation (signal-first APIs) and expands the Angular sample app to showcase bothhttpResourceandhttpResource + Zodflows alongside the existingHttpClientoutput.Related issue
httpResourceAPI #2316httpResourceAPI #2316 (comment)Primary focus — httpResource generation (packages/angular + core)
override.operations.<operationId>.angular.clientto forcehttpResource,httpClient, orboth.ResourceState<T>andtoResourceState) for ergonomic status handling in signal-based flows.httpResource,.text,.arrayBuffer,.blob).schemas.type: 'zod'(with an opt-out viaruntimeValidation: false).*.resource.ts) to emit resources alongside HttpClient output.Expanded Angular sample app (samples/angular-app)
/http-resource— demonstrates signal-firsthttpResourceusage./http-resource-zod— demonstrateshttpResourcewith Zod runtime validation.orval.config.tsto generate newhttp-resourceandhttp-resource-zodoutputs, including mock support.Docs & guidance
httpResourceoutput, configuration, and Zod runtime validation behaviors.httpResource(Angular v19.2+).Other improvements / related fixes
runtimeValidation,client,provideIn).httpResourceand Zod validation toggles.http-resourceandhttp-clientoutputs.lint:generated(root script + Turbo task + tests workspace script) to validate generated outputs ingenerated, which are updated by this PR’s new Angular httpResource fixtures.Angular Query compatibility fix
Aligns generated Angular Query mutation onSuccess callbacks with the current TanStack Query signature (adds context argument).
Required because this PR updates the Angular catalogs and sample outputs; without it, the Angular Query samples fail to typecheck.
Other unrelated changes
Tests
packages/angular/src/http-resource.tsandpackages/angular/src/http-client.ts.