Angular-style schematics for the NestJS framework, enabling generation of application components through a command-line interface.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive toolkit for TypeScript/JavaScript code manipulation, module management, and project structure operations. Provides AST parsers, file system helpers, and NestJS-specific utilities for programmatic code generation and modification.
Manages metadata entries within @Module decorators, allowing programmatic insertion of providers, controllers, imports, and exports.
/**
* Manages metadata entries within @Module decorators
*/
class MetadataManager {
/**
* Insert metadata entry into a module decorator
* @param metadata - Type of metadata ('providers', 'controllers', 'imports', 'exports')
* @param symbol - Symbol name to insert
* @param staticOptions - Optional static configuration
* @returns Updated content or undefined if insertion failed
*/
insert(
metadata: string,
symbol: string,
staticOptions?: DeclarationOptions['staticOptions']
): string | undefined;
}Usage Examples:
import { MetadataManager } from '@nestjs/schematics';
const manager = new MetadataManager();
// Insert provider into module
const updatedContent = manager.insert('providers', 'UserService');
// Insert with static options
const updatedContent2 = manager.insert('providers', 'ConfigService', {
name: 'CONFIG_OPTIONS',
value: 'configOptions'
});Main orchestrator for module imports and metadata declarations, combining import and metadata operations.
/**
* Main orchestrator for module imports and metadata declarations
*/
class ModuleDeclarator {
/**
* Declare module imports and metadata
* @param content - Source file content
* @param options - Declaration configuration
* @returns Updated file content
*/
declare(content: string, options: DeclarationOptions): string;
}
interface DeclarationOptions {
/** Metadata type to modify */
metadata: string;
/** Symbol to declare */
symbol: string;
/** Symbol type (class, function, etc.) */
type?: string;
/** Static options for configuration */
staticOptions?: {
name: string;
value: string;
};
}Usage Examples:
import { ModuleDeclarator } from '@nestjs/schematics';
const declarator = new ModuleDeclarator();
// Declare service in module
const updatedContent = declarator.declare(moduleContent, {
metadata: 'providers',
symbol: 'UserService',
type: 'class'
});
// Declare controller with import
const updatedContent2 = declarator.declare(moduleContent, {
metadata: 'controllers',
symbol: 'AuthController',
type: 'class'
});Handles import statement declarations in TypeScript files.
/**
* Declares module imports in TypeScript files
*/
class ModuleImportDeclarator {
/**
* Declare import statements in file content
* @param content - Source file content
* @param options - Import declaration options
* @returns Updated file content with imports
*/
declare(content: string, options: DeclarationOptions): string;
}Handles metadata declarations within module decorators.
/**
* Declares metadata in TypeScript files
*/
class ModuleMetadataDeclarator {
/**
* Declare metadata in module decorators
* @param content - Source file content
* @param options - Metadata declaration options
* @returns Updated file content with metadata
*/
declare(content: string, options: DeclarationOptions): string;
}Locates module files within directory structures, supporting various naming conventions and patterns.
/**
* Finds module files in directory structures
*/
class ModuleFinder {
/**
* Find module file based on options
* @param options - Search configuration
* @returns Path to found module or null
*/
find(options: FindOptions): Path | null;
}
interface FindOptions {
/** Module name to search for */
name: string;
/** Base path to search in */
path: Path;
}Usage Examples:
import { ModuleFinder } from '@nestjs/schematics';
const finder = new ModuleFinder();
// Find app module
const appModulePath = finder.find({
name: 'app',
path: '/src' as Path
});
// Find specific module
const userModulePath = finder.find({
name: 'users',
path: '/src/users' as Path
});Computes relative paths between different locations in the project structure.
/**
* Computes relative paths between locations
*/
class PathSolver {
/**
* Calculate relative path between two locations
* @param from - Source path
* @param to - Target path
* @returns Relative path string
*/
relative(from: Path, to: Path): string;
}Usage Examples:
import { PathSolver } from '@nestjs/schematics';
const solver = new PathSolver();
// Calculate import path
const relativePath = solver.relative(
'/src/users/users.controller.ts' as Path,
'/src/users/users.service.ts' as Path
);
// Result: './users.service'Parses names and paths for schematics, handling various naming conventions and path structures.
/**
* Parses names and paths for schematics
*/
class NameParser {
/**
* Parse name and path options into location structure
* @param options - Parsing configuration
* @returns Parsed location with name and path
*/
parse(options: ParseOptions): Location;
}
interface ParseOptions {
/** Component name (can include path) */
name: string;
/** Base path for generation */
path?: string;
}
interface Location {
/** Parsed component name */
name: string;
/** Resolved path */
path: Path;
}Usage Examples:
import { NameParser } from '@nestjs/schematics';
const parser = new NameParser();
// Parse simple name
const location1 = parser.parse({ name: 'user-service' });
// Result: { name: 'user-service', path: '.' }
// Parse name with path
const location2 = parser.parse({
name: 'auth/auth-service',
path: 'src/modules'
});
// Result: { name: 'auth-service', path: 'src/modules/auth' }
// Parse kebab-case to different formats
const location3 = parser.parse({ name: 'user-profile-service' });
// Handles conversion to UserProfileService, user-profile-service, etc.Advanced JSON file manipulation with AST parsing, supporting comments and complex modifications.
/**
* JSON file manipulation with AST parsing
*/
class JSONFile {
/**
* Get value at JSON path
* @param jsonPath - Array representing path to value
* @returns Value at path or undefined
*/
get(jsonPath: JSONPath): unknown;
/**
* Modify value at JSON path
* @param jsonPath - Array representing path to value
* @param value - New value to set
* @param insertInOrder - Optional insertion order function
*/
modify(
jsonPath: JSONPath,
value: JsonValue | undefined,
insertInOrder?: InsertionIndex | false
): void;
/**
* Remove value at JSON path
* @param jsonPath - Array representing path to remove
*/
remove(jsonPath: JSONPath): void;
}
type JSONPath = (string | number)[];
type InsertionIndex = (properties: string[]) => number;
type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
interface JsonObject { [key: string]: JsonValue; }
interface JsonArray extends Array<JsonValue> {}Usage Examples:
import { JSONFile } from '@nestjs/schematics';
// Create JSONFile instance from tree
const packageJson = new JSONFile(tree, 'package.json');
// Get dependency version
const nestVersion = packageJson.get(['dependencies', '@nestjs/core']);
// Add new dependency
packageJson.modify(['dependencies', 'lodash'], '^4.17.21');
// Add script with ordered insertion
packageJson.modify(['scripts', 'test:e2e'], 'jest --config ./test/jest-e2e.json',
(props) => props.sort().indexOf('test:e2e')
);
// Remove devDependency
packageJson.remove(['devDependencies', 'old-package']);Various string formatting utilities for consistent naming conventions.
/**
* Normalize string to kebab-case or snake_case
* @param str - Input string
* @returns Normalized string
*/
function normalizeToKebabOrSnakeCase(str: string): string;Usage Examples:
import { normalizeToKebabOrSnakeCase } from '@nestjs/schematics';
// Convert various formats
const kebab1 = normalizeToKebabOrSnakeCase('UserService'); // 'user-service'
const kebab2 = normalizeToKebabOrSnakeCase('user_profile'); // 'user-profile'
const kebab3 = normalizeToKebabOrSnakeCase('API_KEY'); // 'api-key'Utilities for organizing object properties in consistent order.
/**
* Sort object properties in place by keys
* @param object - Object to sort
* @returns Sorted object
*/
function inPlaceSortByKeys(object: Record<string, any>): Record<string, any>;Usage Examples:
import { inPlaceSortByKeys } from '@nestjs/schematics';
const config = {
providers: ['ServiceA'],
imports: ['ModuleB'],
controllers: ['ControllerC'],
exports: ['ServiceA']
};
// Sort for consistent output
const sortedConfig = inPlaceSortByKeys(config);
// Result: { controllers: [...], exports: [...], imports: [...], providers: [...] }Utilities for managing source root directories in projects.
/**
* Check if generation is happening in root directory
* @param host - Virtual file system tree
* @param extraFiles - Additional files to check for
* @returns True if in root directory
*/
function isInRootDirectory(host: Tree, extraFiles?: string[]): boolean;
/**
* Merge source root configuration into options
* @param options - Schematic options
* @returns Rule for merging source root
*/
function mergeSourceRoot<T>(options: T): Rule;Usage Examples:
import { isInRootDirectory, mergeSourceRoot } from '@nestjs/schematics';
// Check if in root
const inRoot = isInRootDirectory(tree, ['nest-cli.json']);
// Apply source root merging
return chain([
mergeSourceRoot(options),
// ... other rules
]);Functions for managing package.json dependencies programmatically.
/**
* Add dependency to package.json
* @param tree - Virtual file system
* @param dependency - Dependency specification
* @param pkgJsonPath - Optional package.json path
*/
function addPackageJsonDependency(
tree: Tree,
dependency: NodeDependency,
pkgJsonPath?: string
): void;
/**
* Get dependency from package.json
* @param tree - Virtual file system
* @param name - Dependency name
* @param pkgJsonPath - Optional package.json path
* @returns Dependency specification or null
*/
function getPackageJsonDependency(
tree: Tree,
name: string,
pkgJsonPath?: string
): NodeDependency | null;
interface NodeDependency {
type: NodeDependencyType;
name: string;
version: string;
overwrite?: boolean;
}
enum NodeDependencyType {
Default = 'dependencies',
Dev = 'devDependencies',
Peer = 'peerDependencies',
Optional = 'optionalDependencies'
}Usage Examples:
import {
addPackageJsonDependency,
getPackageJsonDependency,
NodeDependencyType
} from '@nestjs/schematics';
// Add production dependency
addPackageJsonDependency(tree, {
type: NodeDependencyType.Default,
name: '@nestjs/jwt',
version: '^8.0.0'
});
// Add dev dependency
addPackageJsonDependency(tree, {
type: NodeDependencyType.Dev,
name: '@types/jest',
version: '^27.0.0',
overwrite: true
});
// Check existing dependency
const existing = getPackageJsonDependency(tree, '@nestjs/core');
if (existing) {
console.log(`Found ${existing.name}@${existing.version}`);
}Abstract interface for file reading operations with sync and async support.
/**
* Interface for file reading operations
*/
interface Reader {
/** List available files */
list(): string[] | Promise<string[]>;
/** Read file content (async) */
read(name: string): string | Promise<string>;
/** Read file content (sync) */
readSync(name: string): string;
/** Read any of the specified files (async) */
readAnyOf(filenames: string[]): string | Promise<string | undefined>;
/** Read any of the specified files (sync) */
readSyncAnyOf(filenames: string[]): string | undefined;
}Concrete implementation of Reader for file system operations.
/**
* File system implementation of Reader interface
*/
class FileSystemReader implements Reader {
/**
* Create file system reader
* @param directory - Base directory for file operations
*/
constructor(private readonly directory: string);
list(): string[];
read(name: string): string;
readSync(name: string): string;
readAnyOf(filenames: string[]): string | undefined;
readSyncAnyOf(filenames: string[]): string | undefined;
}Usage Examples:
import { FileSystemReader } from '@nestjs/schematics';
// Create reader for templates directory
const reader = new FileSystemReader('./templates');
// List available template files
const templates = reader.list();
// Read specific template
const controllerTemplate = reader.readSync('controller.template.ts');
// Read any available config file
const config = reader.readSyncAnyOf([
'nest-cli.json',
'angular.json',
'.nestcli.json'
]);Pre-configured values for consistent project generation.
/** Default application author */
const DEFAULT_AUTHOR: string = '';
/** Default application description */
const DEFAULT_DESCRIPTION: string = '';
/** Default programming language */
const DEFAULT_LANGUAGE: string = 'ts';
/** Default application version */
const DEFAULT_VERSION: string = '0.0.1';
/** Default source path name */
const DEFAULT_PATH_NAME: string = 'src';
/** Default libraries path for monorepo */
const DEFAULT_LIB_PATH: string = 'libs';
/** Default applications path for monorepo */
const DEFAULT_APPS_PATH: string = 'apps';
/** Default application name */
const DEFAULT_APP_NAME: string = 'app';
/** Default directory entry for app */
const DEFAULT_DIR_ENTRY_APP: string = 'main';
/** Test environment identifier */
const TEST_ENV: string = 'test';
/** Project type constants */
const PROJECT_TYPE: {
readonly LIBRARY: 'library';
readonly APPLICATION: 'application';
};All utilities are designed to work seamlessly with Angular DevKit's schematic system:
// Common Angular DevKit types used throughout utilities
type Tree = import('@angular-devkit/schematics').Tree;
type Rule = import('@angular-devkit/schematics').Rule;
type SchematicContext = import('@angular-devkit/schematics').SchematicContext;
type Path = import('@angular-devkit/core').Path;These utilities provide the foundation for all NestJS schematics, enabling consistent and reliable code generation across the entire framework ecosystem.