2023-12-07 23:22:28 +00:00
/ * *
* @license
* Copyright Google LLC All Rights Reserved .
*
* Use of this source code is governed by an MIT - style license that can be
2024-09-20 15:23:15 +00:00
* found in the LICENSE file at https : //angular.dev/license
2023-12-07 23:22:28 +00:00
* /
2025-03-07 00:00:55 +00:00
import type { ɵ FrameworkAgnosticGlobalUtils as GlobalUtils } from '@angular/core' ;
2025-07-21 13:45:32 +00:00
import { getAppRoots } from '../component-tree/get-roots' ;
2025-03-27 15:26:53 +00:00
import { Framework } from '../component-tree/core-enums' ;
2023-12-07 23:22:28 +00:00
2025-03-27 15:26:53 +00:00
/** Returns a handle to window.ng APIs (global angular debugging). */
2025-08-05 12:39:18 +00:00
export const ngDebugClient = ( ) = > {
if ( typeof ( window as any ) . ng === 'undefined' ) {
throw new Error (
'Angular DevTools: Angular debugging APIs are not available. Ensure that your Angular app is in development mode and does not invoke `enableProdMode()`.' ,
) ;
}
return ( window as any ) . ng as Partial < GlobalUtils > ;
} ;
2023-12-07 23:22:28 +00:00
2025-03-27 15:26:53 +00:00
/** Type guard that checks whether a given debug API is supported within window.ng */
2025-03-07 00:00:55 +00:00
export function ngDebugApiIsSupported < T extends Partial < GlobalUtils > , K extends keyof T > (
ng : T ,
api : K ,
) : ng is T & Record < K , NonNullable < T [ K ] > > {
2023-12-07 23:22:28 +00:00
return typeof ng [ api ] === 'function' ;
}
2025-03-27 15:26:53 +00:00
/** Checks whether Dependency Injection debug API is supported within window.ng */
2023-12-07 23:22:28 +00:00
export function ngDebugDependencyInjectionApiIsSupported ( ) : boolean {
2025-03-05 23:31:05 +00:00
const ng = ngDebugClient ( ) ;
if ( ! ngDebugApiIsSupported ( ng , 'getInjector' ) ) {
2025-03-04 22:49:53 +00:00
return false ;
}
2025-03-05 23:31:05 +00:00
if ( ! ngDebugApiIsSupported ( ng , 'ɵgetInjectorResolutionPath' ) ) {
2023-12-07 23:22:28 +00:00
return false ;
}
2025-03-05 23:31:05 +00:00
if ( ! ngDebugApiIsSupported ( ng , 'ɵgetDependenciesFromInjectable' ) ) {
2023-12-07 23:22:28 +00:00
return false ;
}
2025-03-05 23:31:05 +00:00
if ( ! ngDebugApiIsSupported ( ng , 'ɵgetInjectorProviders' ) ) {
2023-12-07 23:22:28 +00:00
return false ;
}
2025-03-05 23:31:05 +00:00
if ( ! ngDebugApiIsSupported ( ng , 'ɵgetInjectorMetadata' ) ) {
2023-12-07 23:22:28 +00:00
return false ;
}
return true ;
}
2025-03-27 15:26:53 +00:00
/** Checks whether Profiler API is supported within window.ng */
export function ngDebugProfilerApiIsSupported ( ) : boolean {
const ng = ngDebugClient ( ) ;
// Temporary solution. Convert to an eligible API when available.
// https://github.com/angular/angular/pull/60585#discussion_r2017047132
// If there is a Wiz application, make Profiler API unavailable.
2025-07-21 13:45:32 +00:00
const roots = getAppRoots ( ) ;
2025-03-27 15:26:53 +00:00
return (
! ! roots . length &&
2025-04-23 19:01:43 +00:00
! roots . some ( ( el ) = > {
const comp = ng . getComponent ! ( el ) ! ;
return ng . getDirectiveMetadata ? . ( comp ) ? . framework === Framework . Wiz ;
} )
2025-03-27 15:26:53 +00:00
) ;
}
/** Checks whether Router API is supported within window.ng */
export function ngDebugRoutesApiIsSupported ( ) : boolean {
const ng = ngDebugClient ( ) ;
return (
2025-08-11 02:52:59 +00:00
ngDebugApiIsSupported ( ng , 'ɵgetLoadedRoutes' ) &&
ngDebugApiIsSupported ( ng , 'ɵgetRouterInstance' ) &&
ngDebugApiIsSupported ( ng , 'ɵnavigateByUrl' )
2025-03-27 15:26:53 +00:00
) ;
}
2025-05-20 01:50:36 +00:00
/** Checks whether Signal Graph API is supported within window.ng */
export function ngDebugSignalGraphApiIsSupported ( ) : boolean {
const ng = ngDebugClient ( ) ;
return ngDebugApiIsSupported ( ng , 'ɵgetSignalGraph' ) ;
}
2025-07-18 12:15:07 +00:00
/ * *
* Checks if transfer state is available .
* Transfer state is only relevant when Angular app uses Server - Side Rendering .
* /
export function ngDebugTransferStateApiIsSupported ( ) : boolean {
const ng = ngDebugClient ( ) ;
return ngDebugApiIsSupported ( ng , 'ɵgetTransferState' ) ;
}
2025-05-13 16:19:35 +00:00
/** Checks whether signal properties inspection API is supported within window.ng */
export function ngDebugSignalPropertiesInspectionApiIsSupported ( ) : boolean {
const ng = ngDebugClient ( ) ;
// If all apps are Angular, make the API available.
2025-08-20 09:15:11 +00:00
const roots = getAppRoots ( ) ;
2025-05-13 16:19:35 +00:00
return (
! ! roots . length &&
roots . every ( ( el ) = > {
const comp = ng . getComponent ! ( el ) ! ;
const fw = ng . getDirectiveMetadata ? . ( comp ) ? . framework ;
// `framework` might be optional in the case of `AngularDirectiveDebugMetadata`.
return ! fw || fw === Framework . Angular ;
} )
) ;
}