Angular schematics collection providing code generators for Angular applications, components, services, and other constructs.
—
Utilities for working with Angular's standalone components and bootstrap configuration, supporting the modern Angular application architecture without NgModules.
Functions for adding imports to the root application configuration in standalone applications.
/**
* Adds an import to the root of the project
* @param options - Options for the root import
* @returns Rule that adds the import
*/
function addRootImport(options: AddRootImportOptions): Rule;Usage Example:
import { addRootImport } from '@schematics/angular/utility';
// Add router import to standalone app
export function addRouter(): Rule {
return addRootImport({
import: 'RouterModule.forRoot(routes)',
from: '@angular/router'
});
}
// Add HTTP client import
export function addHttpClient(): Rule {
return addRootImport({
import: 'HttpClientModule',
from: '@angular/common/http'
});
}Functions for adding providers to the root application configuration.
/**
* Adds a provider to the root of the project
* @param options - Options for the root provider
* @returns Rule that adds the provider
*/
function addRootProvider(options: AddRootProviderOptions): Rule;Usage Examples:
import { addRootProvider } from '@schematics/angular/utility';
// Add router provider
export function addRouterProvider(): Rule {
return addRootProvider({
expression: 'provideRouter(routes)',
import: 'provideRouter',
from: '@angular/router'
});
}
// Add HTTP client provider
export function addHttpClientProvider(): Rule {
return addRootProvider({
expression: 'provideHttpClient()',
import: 'provideHttpClient',
from: '@angular/common/http'
});
}
// Add custom service provider
export function addCustomProvider(): Rule {
return addRootProvider({
expression: 'provideMyService({ apiUrl: "https://api.example.com" })',
import: 'provideMyService',
from: './my-service'
});
}Low-level utilities for managing code blocks and pending code modifications.
/**
* Generated code that hasn't been interpolated yet
*/
interface PendingCode {
/** Code that will be inserted */
expression: string;
/** Imports that need to be added to the file in which the code is inserted */
imports: Map<string, Map<string, string>>;
}
/**
* Callback invoked by a Rule that produces the code that needs to be inserted somewhere in the app
* @param block - CodeBlock instance for generating code
* @returns PendingCode object with expression and imports
*/
type CodeBlockCallback = (block: CodeBlock) => PendingCode;
/**
* Utility class used to generate blocks of code that can be inserted by the devkit into a user's app
*/
class CodeBlock {
/**
* Function used to tag a code block in order to produce a PendingCode object
* @param strings - Template strings array
* @param params - Template parameters
* @returns PendingCode object
*/
code(strings: TemplateStringsArray, ...params: unknown[]): PendingCode;
/**
* Function used to reference an external symbol that should be imported
* @param name - Name of the symbol to import
* @param moduleSpecifier - Module to import from
* @returns String reference to the symbol
*/
external(name: string, moduleSpecifier: string): string;
/**
* Transforms a PendingCode object into a format that can be inserted into a file
* @param pendingCode - Code to transform
* @param filePath - Target file path
* @returns Transformed PendingCode
*/
static transformPendingCode(pendingCode: PendingCode, filePath: string): PendingCode;
}import { addRootProvider } from '@schematics/angular/utility';
import { chain } from '@angular-devkit/schematics';
export function setupCompleteApp(): Rule {
return chain([
// Add router
addRootProvider('default', ({code, external}) => {
return code`${external('provideRouter', '@angular/router')}(routes)`;
}),
// Add HTTP client with features
addRootProvider('default', ({code, external}) => {
return code`${external('provideHttpClient', '@angular/common/http')}(
${external('withFetch', '@angular/common/http')}(),
${external('withInterceptors', '@angular/common/http')}([loggingInterceptor])
)`;
}),
// Add animations
addRootProvider('default', ({code, external}) => {
return code`${external('provideAnimations', '@angular/platform-browser/animations')}()`;
})
]);
}import { addRootProvider } from '@schematics/angular/utility';
export function conditionalProvider(): Rule {
return async (tree: Tree, context: SchematicContext) => {
// Check if app uses standalone architecture
const mainPath = '/src/main.ts';
const mainContent = tree.readText(mainPath);
if (mainContent.includes('bootstrapApplication')) {
return addRootProvider('default', ({code, external}) => {
return code`${external('provideMyFeature', './my-feature')}()`;
});
}
// Handle module-based app differently
context.logger.info('Module-based app detected, skipping standalone provider');
return noop();
};
}import { addRootProvider } from '@schematics/angular/utility';
export function addConfiguredProvider(): Rule {
return addRootProvider('default', ({code, external}) => {
return code`${external('provideMyService', '@my-org/my-service')}({
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3
})`;
});
}import { addRootProvider } from '@schematics/angular/utility';
export function addMultipleProviders(): Rule {
return addRootProvider('default', ({code, external}) => {
return code`
${external('provideStore', '@ngrx/store')}(reducers),
${external('provideEffects', '@ngrx/effects')}([UserEffects, ProductEffects])
`;
});
}For applications that haven't migrated to standalone, these utilities will gracefully handle the differences:
import { addRootProvider } from '@schematics/angular/utility';
// This will work in both standalone and module-based apps
export function universalProvider(): Rule {
return (tree: Tree, context: SchematicContext) => {
const mainPath = '/src/main.ts';
const mainContent = tree.readText(mainPath);
if (mainContent.includes('bootstrapApplication')) {
// Standalone app - add to providers array
return addRootProvider({
expression: 'provideMyFeature()',
import: 'provideMyFeature',
from: './my-feature'
});
} else {
// Module-based app - would need to use module utilities instead
context.logger.warn('Module-based app detected. Consider migrating to standalone.');
return noop();
}
};
}The standalone utilities include built-in error handling for common scenarios:
Install with Tessl CLI
npx tessl i tessl/npm-schematics--angular