@angular/common 17.0.0-next.7 → 17.0.0-next.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/esm2022/http/public_api.mjs +1 -1
  2. package/esm2022/http/src/client.mjs +6 -4
  3. package/esm2022/http/src/errors.mjs +1 -1
  4. package/esm2022/http/src/fetch.mjs +3 -3
  5. package/esm2022/http/src/interceptor.mjs +27 -5
  6. package/esm2022/http/src/jsonp.mjs +6 -6
  7. package/esm2022/http/src/module.mjs +12 -12
  8. package/esm2022/http/src/provider.mjs +14 -1
  9. package/esm2022/http/src/request.mjs +3 -1
  10. package/esm2022/http/src/transfer_cache.mjs +73 -18
  11. package/esm2022/http/src/xhr.mjs +3 -3
  12. package/esm2022/http/src/xsrf.mjs +6 -6
  13. package/esm2022/http/testing/src/backend.mjs +3 -3
  14. package/esm2022/http/testing/src/module.mjs +4 -4
  15. package/esm2022/src/common_module.mjs +4 -4
  16. package/esm2022/src/directives/ng_class.mjs +3 -3
  17. package/esm2022/src/directives/ng_component_outlet.mjs +3 -3
  18. package/esm2022/src/directives/ng_for_of.mjs +3 -3
  19. package/esm2022/src/directives/ng_if.mjs +3 -3
  20. package/esm2022/src/directives/ng_optimized_image/index.mjs +3 -2
  21. package/esm2022/src/directives/ng_optimized_image/lcp_image_observer.mjs +3 -3
  22. package/esm2022/src/directives/ng_optimized_image/ng_optimized_image.mjs +6 -16
  23. package/esm2022/src/directives/ng_optimized_image/preconnect_link_checker.mjs +3 -3
  24. package/esm2022/src/directives/ng_optimized_image/preload-link-creator.mjs +3 -3
  25. package/esm2022/src/directives/ng_plural.mjs +6 -6
  26. package/esm2022/src/directives/ng_style.mjs +3 -3
  27. package/esm2022/src/directives/ng_switch.mjs +21 -12
  28. package/esm2022/src/directives/ng_switch_equality.mjs +13 -0
  29. package/esm2022/src/directives/ng_template_outlet.mjs +3 -3
  30. package/esm2022/src/errors.mjs +1 -1
  31. package/esm2022/src/i18n/localization.mjs +6 -6
  32. package/esm2022/src/location/hash_location_strategy.mjs +3 -3
  33. package/esm2022/src/location/location.mjs +3 -3
  34. package/esm2022/src/location/location_strategy.mjs +6 -6
  35. package/esm2022/src/location/platform_location.mjs +6 -6
  36. package/esm2022/src/pipes/async_pipe.mjs +3 -3
  37. package/esm2022/src/pipes/case_conversion_pipes.mjs +9 -9
  38. package/esm2022/src/pipes/date_pipe.mjs +3 -3
  39. package/esm2022/src/pipes/date_pipe_config.mjs +1 -1
  40. package/esm2022/src/pipes/i18n_plural_pipe.mjs +3 -3
  41. package/esm2022/src/pipes/i18n_select_pipe.mjs +3 -3
  42. package/esm2022/src/pipes/json_pipe.mjs +3 -3
  43. package/esm2022/src/pipes/keyvalue_pipe.mjs +3 -3
  44. package/esm2022/src/pipes/number_pipe.mjs +9 -9
  45. package/esm2022/src/pipes/slice_pipe.mjs +3 -3
  46. package/esm2022/src/version.mjs +1 -1
  47. package/esm2022/testing/src/location_mock.mjs +3 -3
  48. package/esm2022/testing/src/mock_location_strategy.mjs +3 -3
  49. package/esm2022/testing/src/mock_platform_location.mjs +3 -3
  50. package/esm2022/upgrade/src/location_upgrade_module.mjs +4 -4
  51. package/fesm2022/common.mjs +134 -131
  52. package/fesm2022/common.mjs.map +1 -1
  53. package/fesm2022/http/testing.mjs +8 -8
  54. package/fesm2022/http.mjs +147 -55
  55. package/fesm2022/http.mjs.map +1 -1
  56. package/fesm2022/testing.mjs +10 -10
  57. package/fesm2022/upgrade.mjs +5 -5
  58. package/http/index.d.ts +271 -4
  59. package/http/testing/index.d.ts +1 -1
  60. package/index.d.ts +7 -22
  61. package/package.json +3 -2
  62. package/testing/index.d.ts +1 -1
  63. package/upgrade/index.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v17.0.0-next.7
2
+ * @license Angular v17.0.0-next.8
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -308,10 +308,10 @@ class HttpClientTestingBackend {
308
308
  return `Match by function: ${matcher.name}`;
309
309
  }
310
310
  }
311
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
312
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingBackend }); }
311
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
312
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingBackend }); }
313
313
  }
314
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingBackend, decorators: [{
314
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingBackend, decorators: [{
315
315
  type: Injectable
316
316
  }] });
317
317
  function describeRequest(testRequest) {
@@ -336,13 +336,13 @@ function provideHttpClientTesting() {
336
336
  * @publicApi
337
337
  */
338
338
  class HttpClientTestingModule {
339
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
340
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingModule, imports: [HttpClientModule] }); }
341
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingModule, providers: [
339
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
340
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingModule, imports: [HttpClientModule] }); }
341
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingModule, providers: [
342
342
  provideHttpClientTesting(),
343
343
  ], imports: [HttpClientModule] }); }
344
344
  }
345
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientTestingModule, decorators: [{
345
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientTestingModule, decorators: [{
346
346
  type: NgModule,
347
347
  args: [{
348
348
  imports: [
package/fesm2022/http.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  /**
2
- * @license Angular v17.0.0-next.7
2
+ * @license Angular v17.0.0-next.8
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { Injectable, inject, NgZone, InjectionToken, ɵInitialRenderPendingTasks, Inject, ɵRuntimeError, PLATFORM_ID, makeEnvironmentProviders, NgModule, TransferState, makeStateKey, ɵENABLED_SSR_FEATURES, APP_BOOTSTRAP_LISTENER, ApplicationRef, ɵwhenStable } from '@angular/core';
8
+ import { Injectable, inject, NgZone, InjectionToken, ɵInitialRenderPendingTasks, PLATFORM_ID, ɵConsole, ɵformatRuntimeError, Inject, ɵRuntimeError, makeEnvironmentProviders, NgModule, TransferState, makeStateKey, ɵENABLED_SSR_FEATURES, APP_BOOTSTRAP_LISTENER, ApplicationRef, ɵwhenStable, ɵtruncateMiddle } from '@angular/core';
9
9
  import { of, Observable, from } from 'rxjs';
10
10
  import { concatMap, filter, map, finalize, switchMap, tap } from 'rxjs/operators';
11
11
  import * as i1 from '@angular/common';
12
- import { DOCUMENT, ɵparseCookieValue } from '@angular/common';
12
+ import { isPlatformServer, DOCUMENT, ɵparseCookieValue } from '@angular/common';
13
13
 
14
14
  /**
15
15
  * Transforms an `HttpRequest` into a stream of `HttpEvent`s, one of which will likely be a
@@ -771,6 +771,8 @@ class HttpRequest {
771
771
  if (!!options.params) {
772
772
  this.params = options.params;
773
773
  }
774
+ // We do want to assign transferCache even if it's falsy (false is valid value)
775
+ this.transferCache = options.transferCache;
774
776
  }
775
777
  // If no headers have been passed in, construct a new HttpHeaders instance.
776
778
  if (!this.headers) {
@@ -1093,6 +1095,7 @@ function addBody(options, body) {
1093
1095
  reportProgress: options.reportProgress,
1094
1096
  responseType: options.responseType,
1095
1097
  withCredentials: options.withCredentials,
1098
+ transferCache: options.transferCache,
1096
1099
  };
1097
1100
  }
1098
1101
  /**
@@ -1219,6 +1222,7 @@ class HttpClient {
1219
1222
  // By default, JSON is assumed to be returned for all calls.
1220
1223
  responseType: options.responseType || 'json',
1221
1224
  withCredentials: options.withCredentials,
1225
+ transferCache: options.transferCache,
1222
1226
  });
1223
1227
  }
1224
1228
  // Start with an Observable.of() the initial request, and run the handler (which
@@ -1373,10 +1377,10 @@ class HttpClient {
1373
1377
  put(url, body, options = {}) {
1374
1378
  return this.request('PUT', url, addBody(options, body));
1375
1379
  }
1376
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClient, deps: [{ token: HttpHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
1377
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClient }); }
1380
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClient, deps: [{ token: HttpHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
1381
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClient }); }
1378
1382
  }
1379
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClient, decorators: [{
1383
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClient, decorators: [{
1380
1384
  type: Injectable
1381
1385
  }], ctorParameters: () => [{ type: HttpHandler }] });
1382
1386
 
@@ -1581,10 +1585,10 @@ class FetchBackend {
1581
1585
  }
1582
1586
  return chunksAll;
1583
1587
  }
1584
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: FetchBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1585
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: FetchBackend }); }
1588
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: FetchBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1589
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: FetchBackend }); }
1586
1590
  }
1587
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: FetchBackend, decorators: [{
1591
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: FetchBackend, decorators: [{
1588
1592
  type: Injectable
1589
1593
  }] });
1590
1594
  /**
@@ -1663,6 +1667,11 @@ function legacyInterceptorFnFactory() {
1663
1667
  return chain(req, handler).pipe(finalize(() => pendingTasks.remove(taskId)));
1664
1668
  };
1665
1669
  }
1670
+ let fetchBackendWarningDisplayed = false;
1671
+ /** Internal function to reset the flag in tests */
1672
+ function resetFetchBackendWarningFlag() {
1673
+ fetchBackendWarningDisplayed = false;
1674
+ }
1666
1675
  class HttpInterceptorHandler extends HttpHandler {
1667
1676
  constructor(backend, injector) {
1668
1677
  super();
@@ -1675,6 +1684,21 @@ class HttpInterceptorHandler extends HttpHandler {
1675
1684
  // is used.
1676
1685
  const primaryHttpBackend = inject(PRIMARY_HTTP_BACKEND, { optional: true });
1677
1686
  this.backend = primaryHttpBackend ?? backend;
1687
+ // We strongly recommend using fetch backend for HTTP calls when SSR is used
1688
+ // for an application. The logic below checks if that's the case and produces
1689
+ // a warning otherwise.
1690
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) && !fetchBackendWarningDisplayed) {
1691
+ const isServer = isPlatformServer(injector.get(PLATFORM_ID));
1692
+ if (isServer && !(this.backend instanceof FetchBackend)) {
1693
+ fetchBackendWarningDisplayed = true;
1694
+ injector.get(ɵConsole).warn(ɵformatRuntimeError(2801 /* RuntimeErrorCode.NOT_USING_FETCH_BACKEND_IN_SSR */, 'Angular detected that `HttpClient` is not configured ' +
1695
+ 'to use `fetch` APIs. It\'s strongly recommended to ' +
1696
+ 'enable `fetch` for applications that use Server-Side Rendering ' +
1697
+ 'for better performance and compatibility. ' +
1698
+ 'To enable `fetch`, add the `withFetch()` to the `provideHttpClient()` ' +
1699
+ 'call at the root of the application.'));
1700
+ }
1701
+ }
1678
1702
  }
1679
1703
  handle(initialRequest) {
1680
1704
  if (this.chain === null) {
@@ -1692,10 +1716,10 @@ class HttpInterceptorHandler extends HttpHandler {
1692
1716
  return this.chain(initialRequest, downstreamRequest => this.backend.handle(downstreamRequest))
1693
1717
  .pipe(finalize(() => this.pendingTasks.remove(taskId)));
1694
1718
  }
1695
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpInterceptorHandler, deps: [{ token: HttpBackend }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
1696
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpInterceptorHandler }); }
1719
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpInterceptorHandler, deps: [{ token: HttpBackend }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
1720
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpInterceptorHandler }); }
1697
1721
  }
1698
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpInterceptorHandler, decorators: [{
1722
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpInterceptorHandler, decorators: [{
1699
1723
  type: Injectable
1700
1724
  }], ctorParameters: () => [{ type: HttpBackend }, { type: i0.EnvironmentInjector }] });
1701
1725
 
@@ -1897,10 +1921,10 @@ class JsonpClientBackend {
1897
1921
  }
1898
1922
  foreignDocument.adoptNode(script);
1899
1923
  }
1900
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: JsonpClientBackend, deps: [{ token: JsonpCallbackContext }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
1901
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: JsonpClientBackend }); }
1924
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: JsonpClientBackend, deps: [{ token: JsonpCallbackContext }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
1925
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: JsonpClientBackend }); }
1902
1926
  }
1903
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: JsonpClientBackend, decorators: [{
1927
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: JsonpClientBackend, decorators: [{
1904
1928
  type: Injectable
1905
1929
  }], ctorParameters: () => [{ type: JsonpCallbackContext }, { type: undefined, decorators: [{
1906
1930
  type: Inject,
@@ -1938,10 +1962,10 @@ class JsonpInterceptor {
1938
1962
  intercept(initialRequest, next) {
1939
1963
  return this.injector.runInContext(() => jsonpInterceptorFn(initialRequest, downstreamRequest => next.handle(downstreamRequest)));
1940
1964
  }
1941
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: JsonpInterceptor, deps: [{ token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
1942
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: JsonpInterceptor }); }
1965
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: JsonpInterceptor, deps: [{ token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
1966
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: JsonpInterceptor }); }
1943
1967
  }
1944
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: JsonpInterceptor, decorators: [{
1968
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: JsonpInterceptor, decorators: [{
1945
1969
  type: Injectable
1946
1970
  }], ctorParameters: () => [{ type: i0.EnvironmentInjector }] });
1947
1971
 
@@ -2220,10 +2244,10 @@ class HttpXhrBackend {
2220
2244
  });
2221
2245
  }));
2222
2246
  }
2223
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXhrBackend, deps: [{ token: i1.XhrFactory }], target: i0.ɵɵFactoryTarget.Injectable }); }
2224
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXhrBackend }); }
2247
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXhrBackend, deps: [{ token: i1.XhrFactory }], target: i0.ɵɵFactoryTarget.Injectable }); }
2248
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXhrBackend }); }
2225
2249
  }
2226
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXhrBackend, decorators: [{
2250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXhrBackend, decorators: [{
2227
2251
  type: Injectable
2228
2252
  }], ctorParameters: () => [{ type: i1.XhrFactory }] });
2229
2253
 
@@ -2272,10 +2296,10 @@ class HttpXsrfCookieExtractor {
2272
2296
  }
2273
2297
  return this.lastToken;
2274
2298
  }
2275
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXsrfCookieExtractor, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: XSRF_COOKIE_NAME }], target: i0.ɵɵFactoryTarget.Injectable }); }
2276
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXsrfCookieExtractor }); }
2299
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXsrfCookieExtractor, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: XSRF_COOKIE_NAME }], target: i0.ɵɵFactoryTarget.Injectable }); }
2300
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXsrfCookieExtractor }); }
2277
2301
  }
2278
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXsrfCookieExtractor, decorators: [{
2302
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXsrfCookieExtractor, decorators: [{
2279
2303
  type: Injectable
2280
2304
  }], ctorParameters: () => [{ type: undefined, decorators: [{
2281
2305
  type: Inject,
@@ -2315,10 +2339,10 @@ class HttpXsrfInterceptor {
2315
2339
  intercept(initialRequest, next) {
2316
2340
  return this.injector.runInContext(() => xsrfInterceptorFn(initialRequest, downstreamRequest => next.handle(downstreamRequest)));
2317
2341
  }
2318
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXsrfInterceptor, deps: [{ token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
2319
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXsrfInterceptor }); }
2342
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXsrfInterceptor, deps: [{ token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
2343
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXsrfInterceptor }); }
2320
2344
  }
2321
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpXsrfInterceptor, decorators: [{
2345
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpXsrfInterceptor, decorators: [{
2322
2346
  type: Injectable
2323
2347
  }], ctorParameters: () => [{ type: i0.EnvironmentInjector }] });
2324
2348
 
@@ -2351,6 +2375,19 @@ function makeHttpFeature(kind, providers) {
2351
2375
  * feature functions to `provideHttpClient`. For example, HTTP interceptors can be added using the
2352
2376
  * `withInterceptors(...)` feature.
2353
2377
  *
2378
+ * <div class="alert is-helpful">
2379
+ *
2380
+ * It's strongly recommended to enable
2381
+ * [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) for applications that use
2382
+ * Server-Side Rendering for better performance and compatibility. To enable `fetch`, add
2383
+ * `withFetch()` feature to the `provideHttpClient()` call at the root of the application:
2384
+ *
2385
+ * ```
2386
+ * provideHttpClient(withFetch());
2387
+ * ```
2388
+ *
2389
+ * </div>
2390
+ *
2354
2391
  * @see {@link withInterceptors}
2355
2392
  * @see {@link withInterceptorsFromDi}
2356
2393
  * @see {@link withXsrfConfiguration}
@@ -2576,9 +2613,9 @@ class HttpClientXsrfModule {
2576
2613
  providers: withXsrfConfiguration(options).ɵproviders,
2577
2614
  };
2578
2615
  }
2579
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientXsrfModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2580
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientXsrfModule }); }
2581
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientXsrfModule, providers: [
2616
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientXsrfModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2617
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientXsrfModule }); }
2618
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientXsrfModule, providers: [
2582
2619
  HttpXsrfInterceptor,
2583
2620
  { provide: HTTP_INTERCEPTORS, useExisting: HttpXsrfInterceptor, multi: true },
2584
2621
  { provide: HttpXsrfTokenExtractor, useClass: HttpXsrfCookieExtractor },
@@ -2589,7 +2626,7 @@ class HttpClientXsrfModule {
2589
2626
  { provide: XSRF_ENABLED, useValue: true },
2590
2627
  ] }); }
2591
2628
  }
2592
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientXsrfModule, decorators: [{
2629
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientXsrfModule, decorators: [{
2593
2630
  type: NgModule,
2594
2631
  args: [{
2595
2632
  providers: [
@@ -2614,13 +2651,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7",
2614
2651
  * @publicApi
2615
2652
  */
2616
2653
  class HttpClientModule {
2617
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2618
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientModule }); }
2619
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientModule, providers: [
2654
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2655
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientModule }); }
2656
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientModule, providers: [
2620
2657
  provideHttpClient(withInterceptorsFromDi()),
2621
2658
  ] }); }
2622
2659
  }
2623
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientModule, decorators: [{
2660
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientModule, decorators: [{
2624
2661
  type: NgModule,
2625
2662
  args: [{
2626
2663
  /**
@@ -2641,13 +2678,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7",
2641
2678
  * @publicApi
2642
2679
  */
2643
2680
  class HttpClientJsonpModule {
2644
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientJsonpModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2645
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientJsonpModule }); }
2646
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientJsonpModule, providers: [
2681
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientJsonpModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2682
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientJsonpModule }); }
2683
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientJsonpModule, providers: [
2647
2684
  withJsonpSupport().ɵproviders,
2648
2685
  ] }); }
2649
2686
  }
2650
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7", ngImport: i0, type: HttpClientJsonpModule, decorators: [{
2687
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.8", ngImport: i0, type: HttpClientJsonpModule, decorators: [{
2651
2688
  type: NgModule,
2652
2689
  args: [{
2653
2690
  providers: [
@@ -2656,23 +2693,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.7",
2656
2693
  }]
2657
2694
  }] });
2658
2695
 
2659
- const CACHE_STATE = new InjectionToken(ngDevMode ? 'HTTP_TRANSFER_STATE_CACHE_STATE' : '');
2696
+ const CACHE_OPTIONS = new InjectionToken(ngDevMode ? 'HTTP_TRANSFER_STATE_CACHE_OPTIONS' : '');
2660
2697
  /**
2661
2698
  * A list of allowed HTTP methods to cache.
2662
2699
  */
2663
2700
  const ALLOWED_METHODS = ['GET', 'HEAD'];
2664
2701
  function transferCacheInterceptorFn(req, next) {
2665
- const { isCacheActive } = inject(CACHE_STATE);
2666
- // Stop using the cache if the application has stabilized, indicating initial rendering
2667
- // is complete.
2668
- if (!isCacheActive || !ALLOWED_METHODS.includes(req.method)) {
2669
- // Cache is no longer active or method is not HEAD or GET.
2670
- // Pass the request through.
2702
+ const { isCacheActive, ...globalOptions } = inject(CACHE_OPTIONS);
2703
+ const { transferCache: requestOptions, method: requestMethod } = req;
2704
+ // In the following situations we do not want to cache the request
2705
+ if (!isCacheActive ||
2706
+ // POST requests are allowed either globally or at request level
2707
+ (requestMethod === 'POST' && !globalOptions.includePostRequests && !requestOptions) ||
2708
+ (requestMethod !== 'POST' && !ALLOWED_METHODS.includes(requestMethod)) ||
2709
+ requestOptions === false || //
2710
+ (globalOptions.filter?.(req)) === false) {
2671
2711
  return next(req);
2672
2712
  }
2673
2713
  const transferState = inject(TransferState);
2674
2714
  const storeKey = makeCacheKey(req);
2675
2715
  const response = transferState.get(storeKey, null);
2716
+ let headersToInclude = globalOptions.includeHeaders;
2717
+ if (typeof requestOptions === 'object' && requestOptions.includeHeaders) {
2718
+ // Request-specific config takes precedence over the global config.
2719
+ headersToInclude = requestOptions.includeHeaders;
2720
+ }
2676
2721
  if (response) {
2677
2722
  // Request found in cache. Respond using it.
2678
2723
  let body = response.body;
@@ -2684,9 +2729,19 @@ function transferCacheInterceptorFn(req, next) {
2684
2729
  body = new Blob([response.body]);
2685
2730
  break;
2686
2731
  }
2732
+ // We want to warn users accessing a header provided from the cache
2733
+ // That HttpTransferCache alters the headers
2734
+ // The warning will be logged a single time by HttpHeaders instance
2735
+ let headers = new HttpHeaders(response.headers);
2736
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
2737
+ // Append extra logic in dev mode to produce a warning when a header
2738
+ // that was not transferred to the client is accessed in the code via `get`
2739
+ // and `has` calls.
2740
+ headers = appendMissingHeadersDetection(req.url, headers, headersToInclude ?? []);
2741
+ }
2687
2742
  return of(new HttpResponse({
2688
2743
  body,
2689
- headers: new HttpHeaders(response.headers),
2744
+ headers,
2690
2745
  status: response.status,
2691
2746
  statusText: response.statusText,
2692
2747
  url: response.url,
@@ -2697,7 +2752,7 @@ function transferCacheInterceptorFn(req, next) {
2697
2752
  if (event instanceof HttpResponse) {
2698
2753
  transferState.set(storeKey, {
2699
2754
  body: event.body,
2700
- headers: getHeadersMap(event.headers),
2755
+ headers: getFilteredHeaders(event.headers, headersToInclude),
2701
2756
  status: event.status,
2702
2757
  statusText: event.statusText,
2703
2758
  url: event.url || '',
@@ -2706,9 +2761,12 @@ function transferCacheInterceptorFn(req, next) {
2706
2761
  }
2707
2762
  }));
2708
2763
  }
2709
- function getHeadersMap(headers) {
2764
+ function getFilteredHeaders(headers, includeHeaders) {
2765
+ if (!includeHeaders) {
2766
+ return {};
2767
+ }
2710
2768
  const headersMap = {};
2711
- for (const key of headers.keys()) {
2769
+ for (const key of includeHeaders) {
2712
2770
  const values = headers.getAll(key);
2713
2771
  if (values !== null) {
2714
2772
  headersMap[key] = values;
@@ -2751,27 +2809,27 @@ function generateHash(value) {
2751
2809
  * load time.
2752
2810
  *
2753
2811
  */
2754
- function withHttpTransferCache() {
2812
+ function withHttpTransferCache(cacheOptions) {
2755
2813
  return [
2756
2814
  {
2757
- provide: CACHE_STATE,
2815
+ provide: CACHE_OPTIONS,
2758
2816
  useFactory: () => {
2759
2817
  inject(ɵENABLED_SSR_FEATURES).add('httpcache');
2760
- return { isCacheActive: true };
2818
+ return { isCacheActive: true, ...cacheOptions };
2761
2819
  }
2762
2820
  },
2763
2821
  {
2764
2822
  provide: HTTP_ROOT_INTERCEPTOR_FNS,
2765
2823
  useValue: transferCacheInterceptorFn,
2766
2824
  multi: true,
2767
- deps: [TransferState, CACHE_STATE]
2825
+ deps: [TransferState, CACHE_OPTIONS]
2768
2826
  },
2769
2827
  {
2770
2828
  provide: APP_BOOTSTRAP_LISTENER,
2771
2829
  multi: true,
2772
2830
  useFactory: () => {
2773
2831
  const appRef = inject(ApplicationRef);
2774
- const cacheState = inject(CACHE_STATE);
2832
+ const cacheState = inject(CACHE_OPTIONS);
2775
2833
  return () => {
2776
2834
  ɵwhenStable(appRef).then(() => {
2777
2835
  cacheState.isCacheActive = false;
@@ -2781,6 +2839,40 @@ function withHttpTransferCache() {
2781
2839
  }
2782
2840
  ];
2783
2841
  }
2842
+ /**
2843
+ * This function will add a proxy to an HttpHeader to intercept calls to get/has
2844
+ * and log a warning if the header entry requested has been removed
2845
+ */
2846
+ function appendMissingHeadersDetection(url, headers, headersToInclude) {
2847
+ const warningProduced = new Set();
2848
+ return new Proxy(headers, {
2849
+ get(target, prop) {
2850
+ const value = Reflect.get(target, prop);
2851
+ const methods = new Set(['get', 'has', 'getAll']);
2852
+ if (typeof value !== 'function' || !methods.has(prop)) {
2853
+ return value;
2854
+ }
2855
+ return (headerName) => {
2856
+ // We log when the key has been removed and a warning hasn't been produced for the header
2857
+ const key = (prop + ':' + headerName).toLowerCase(); // e.g. `get:cache-control`
2858
+ if (!headersToInclude.includes(headerName) && !warningProduced.has(key)) {
2859
+ warningProduced.add(key);
2860
+ const truncatedUrl = ɵtruncateMiddle(url);
2861
+ // TODO: create Error guide for this warning
2862
+ console.warn(ɵformatRuntimeError(2802 /* RuntimeErrorCode.HEADERS_ALTERED_BY_TRANSFER_CACHE */, `Angular detected that the \`${headerName}\` header is accessed, but the value of the header ` +
2863
+ `was not transferred from the server to the client by the HttpTransferCache. ` +
2864
+ `To include the value of the \`${headerName}\` header for the \`${truncatedUrl}\` request, ` +
2865
+ `use the \`includeHeaders\` list. The \`includeHeaders\` can be defined either ` +
2866
+ `on a request level by adding the \`transferCache\` parameter, or on an application ` +
2867
+ `level by adding the \`httpCacheTransfer.includeHeaders\` argument to the ` +
2868
+ `\`provideClientHydration()\` call. `));
2869
+ }
2870
+ // invoking the original method
2871
+ return value.apply(target, [headerName]);
2872
+ };
2873
+ }
2874
+ });
2875
+ }
2784
2876
 
2785
2877
  // This file is not used to build this module. It is only used during editing
2786
2878