import EventEmitter from 'node:events'; import { QueuedAdapter, type TerminalAdapterOptions } from '@yeoman/adapter'; import type { ApplyTransformsOptions, BaseEnvironment, BaseEnvironmentOptions, BaseGenerator, BaseGeneratorConstructorMeta, BaseGeneratorMeta, ComposeOptions, GeneratorMeta, GetGeneratorConstructor, InputOutputAdapter, InstantiateOptions, LookupGeneratorMeta } from '@yeoman/types'; import { type Store as MemFs } from 'mem-fs'; import { type MemFsEditorFile } from 'mem-fs-editor'; import { FlyRepository } from 'fly-import'; import GroupedQueue from 'grouped-queue'; import { type FilePipelineTransform } from '@yeoman/transform'; import { type YeomanNamespace } from '@yeoman/namespace'; import { type ConflicterOptions } from '@yeoman/conflicter'; import { ComposedStore } from './composed-store.ts'; import Store from './store.ts'; import type YeomanCommand from './util/command.ts'; import { type LookupOptions } from './generator-lookup.ts'; import { type InstallTask } from './package-manager.ts'; export type EnvironmentLookupOptions = LookupOptions & { /** Add a scope to the namespace if there is no scope */ registerToScope?: string; /** Customize the namespace to be registered */ customizeNamespace?: (ns?: string) => string | undefined; }; export type EnvironmentOptions = ConflicterOptions & BaseEnvironmentOptions & Omit & { adapter?: InputOutputAdapter; logCwd?: string; command?: YeomanCommand; yeomanRepository?: string; arboristRegistry?: string; nodePackageManager?: string; generatorLookupOptions?: Pick; }; /** * Copy and remove null and undefined values * @param object * @returns */ export declare function removePropertiesWithNullishValues(object: Record): Record; export default class EnvironmentBase extends EventEmitter implements BaseEnvironment { cwd: string; logCwd: string; adapter: QueuedAdapter; sharedFs: MemFs; conflicterOptions?: ConflicterOptions; readonly sharedOptions: Record; readonly options: EnvironmentOptions; protected readonly aliases: Array<{ match: RegExp; value: string; }>; protected store: Store; protected command?: YeomanCommand; protected runLoop: GroupedQueue; protected composedStore: ComposedStore; protected lookups: string[]; protected repository: FlyRepository; protected experimental: boolean; protected _rootGenerator?: BaseGenerator; protected compatibilityMode?: false | 'v4'; private contextStore; constructor(options?: EnvironmentOptions); findFeature(featureName: string): Array<{ generatorId: string; feature: any; }>; applyTransforms(transformStreams: FilePipelineTransform[], options?: ApplyTransformsOptions): Promise; /** * @param namespaceOrPath * @return the generator meta registered under the namespace */ findMeta(namespaceOrPath: string | YeomanNamespace): GeneratorMeta | undefined; /** * Get a single generator from the registered list of generators. The lookup is * based on generator's namespace, "walking up" the namespaces until a matching * is found. Eg. if an `angular:common` namespace is registered, and we try to * get `angular:common:all` then we get `angular:common` as a fallback (unless * an `angular:common:all` generator is registered). * * @param namespaceOrPath * @return the generator registered under the namespace */ get(namespaceOrPath: string | YeomanNamespace): Promise<(GetGeneratorConstructor & BaseGeneratorConstructorMeta) | undefined> | ((GetGeneratorConstructor & BaseGeneratorConstructorMeta) | undefined); /** * Create is the Generator factory. It takes a namespace to lookup and optional * hash of options, that lets you define `arguments` and `options` to * instantiate the generator with. * * An error is raised on invalid namespace. * * @param namespaceOrPath * @param instantiateOptions * @return The instantiated generator */ create(namespaceOrPath: string | (GetGeneratorConstructor & Partial), instantiateOptions?: InstantiateOptions): Promise; /** * Instantiate a Generator with metadatas * * @param generator Generator class * @param instantiateOptions * @return The instantiated generator */ instantiate(generator: GetGeneratorConstructor, instantiateOptions?: InstantiateOptions): Promise; /** * @protected * Compose with the generator. * * @param {String} namespaceOrPath * @return {Generator} The instantiated generator or the singleton instance. */ composeWith(generator: string | GetGeneratorConstructor, composeOptions?: ComposeOptions): Promise; /** * Given a String `filepath`, tries to figure out the relative namespace. * * ### Examples: * * this.namespace('backbone/all/index.js'); * // => backbone:all * * this.namespace('generator-backbone/model'); * // => backbone:model * * this.namespace('backbone.js'); * // => backbone * * this.namespace('generator-mocha/backbone/model/index.js'); * // => mocha:backbone:model * * @param {String} filepath * @param {Array} lookups paths */ namespace(filepath: string, lookups?: string[]): string; /** * Returns the environment or dependency version. * @param {String} packageName - Module to get version. * @return {String} Environment version. */ getVersion(): string; getVersion(dependency: string): string | undefined; /** * Queue generator run (queue itself tasks). * * @param {Generator} generator Generator instance * @param {boolean} [schedule=false] Whether to schedule the generator run. * @return {Generator} The generator or singleton instance. */ queueGenerator(generator: G, queueOptions?: { schedule?: boolean; }): Promise; /** * Get the first generator that was queued to run in this environment. * * @return {Generator} generator queued to run in this environment. */ rootGenerator(): G; runGenerator(generator: BaseGenerator): Promise; /** * Registers a specific `generator` to this environment. This generator is stored under * provided namespace, or a default namespace format if none if available. * * @param name - Filepath to the a generator or a npm package name * @param namespace - Namespace under which register the generator (optional) * @param packagePath - PackagePath to the generator npm package (optional) * @return environment - This environment */ register(filePath: string, meta?: Partial | undefined): GeneratorMeta; register(generator: unknown, meta: BaseGeneratorMeta): GeneratorMeta; /** * Queue tasks * @param {string} priority * @param {(...args: any[]) => void | Promise} task * @param {{ once?: string, startQueue?: boolean }} [options] */ queueTask(priority: string, task: () => void | Promise, options?: { once?: string | undefined; startQueue?: boolean | undefined; } | undefined): void; /** * Add priority * @param {string} priority * @param {string} [before] */ addPriority(priority: string, before?: string | undefined): void; /** * Search for generators and their sub generators. * * A generator is a `:lookup/:name/index.js` file placed inside an npm package. * * Defaults lookups are: * - ./ * - generators/ * - lib/generators/ * * So this index file `node_modules/generator-dummy/lib/generators/yo/index.js` would be * registered as `dummy:yo` generator. */ lookup(options?: EnvironmentLookupOptions): Promise; /** * Verify if a package namespace already have been registered. * * @param packageNS - namespace of the package. * @return true if any generator of the package has been registered */ isPackageRegistered(packageNamespace: string): boolean; /** * Get all registered packages namespaces. * * @return array of namespaces. */ getRegisteredPackages(): string[]; /** * Returns stored generators meta * @param namespace */ getGeneratorMeta(namespace: string): GeneratorMeta | undefined; /** * Get or create an alias. * * Alias allows the `get()` and `lookup()` methods to search in alternate * filepath for a given namespaces. It's used for example to map `generator-*` * npm package to their namespace equivalent (without the generator- prefix), * or to default a single namespace like `angular` to `angular:app` or * `angular:all`. * * Given a single argument, this method acts as a getter. When both name and * value are provided, acts as a setter and registers that new alias. * * If multiple alias are defined, then the replacement is recursive, replacing * each alias in reverse order. * * An alias can be a single String or a Regular Expression. The finding is done * based on .match(). * * @param {String|RegExp} match * @param {String} value * * @example * * env.alias(/^([a-zA-Z0-9:\*]+)$/, 'generator-$1'); * env.alias(/^([^:]+)$/, '$1:app'); * env.alias(/^([^:]+)$/, '$1:all'); * env.alias('foo'); * // => generator-foo:all */ alias(match: string | RegExp, value: string): this; alias(value: string): string; /** * Watch for package.json and queue package manager install task. */ watchForPackageManagerInstall({ cwd, queueTask, installTask, }?: { cwd?: string; queueTask?: boolean; installTask?: InstallTask; }): void; /** * Start Environment queue * @param {Object} options - Conflicter options. */ protected start(options: any): Promise; /** * Queue environment's commit task. */ protected queueCommit(): void; /** * Registers a specific `generator` to this environment. This generator is stored under * provided namespace, or a default namespace format if none if available. * * @param name - Filepath to the a generator or a npm package name * @param namespace - Namespace under which register the generator (optional) * @param packagePath - PackagePath to the generator npm package (optional) * @return environment - This environment */ protected registerGeneratorPath(generatorPath: string, namespace?: string, packagePath?: string): GeneratorMeta; /** * Register a stubbed generator to this environment. This method allow to register raw * functions under the provided namespace. `registerStub` will enforce the function passed * to extend the Base generator automatically. * * @param Generator - A Generator constructor or a simple function * @param namespace - Namespace under which register the generator * @param resolved - The file path to the generator * @param packagePath - The generator's package path */ protected registerStub(Generator: any, namespace: string, resolved?: string, packagePath?: string): GeneratorMeta; /** * @experimental * Get a map to store shared data, usually a generator root path to share a map by path. */ getContextMap(key: string, factory?: () => Map): Map; }