CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-schematics--angular

Angular schematics collection providing code generators for Angular applications, components, services, and other constructs.

Pending
Overview
Eval results
Files

standalone-utilities.mddocs/

Standalone Utilities

Utilities for working with Angular's standalone components and bootstrap configuration, supporting the modern Angular application architecture without NgModules.

Capabilities

Root Import Management

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'
  });
}

Root Provider Management

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'
  });
}

Code Block Management

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;
}

Advanced Usage

Complex Provider Setup

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')}()`;
    })
  ]);
}

Conditional Provider Addition

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();
  };
}

Custom Provider with Configuration

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
    })`;
  });
}

Multiple Providers

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])
    `;
  });
}

Integration with Module-based Apps

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();
    }
  };
}

Error Handling

The standalone utilities include built-in error handling for common scenarios:

  • Missing main.ts: Utilities will log appropriate errors if the main application file is not found
  • Non-standalone apps: Functions will detect module-based applications and provide appropriate warnings
  • Invalid syntax: Code parsing errors are caught and reported with helpful messages
  • Duplicate providers: The utilities can detect and handle duplicate provider registrations

Install with Tessl CLI

npx tessl i tessl/npm-schematics--angular

docs

ast-utilities.md

dependency-management.md

index.md

schematics.md

standalone-utilities.md

workspace-utilities.md

tile.json