Преглед на файлове

📝 Add docstrings to `feat-cli-noninteractive`

Docstrings generation was requested by @HouseinIsProgramming.

* https://github.com/vendure-ecommerce/vendure/pull/3606#issuecomment-2991616713

The following files were modified:

* `packages/cli/src/commands/add/add-operations.ts`
* `packages/cli/src/commands/add/add.ts`
* `packages/cli/src/commands/add/api-extension/add-api-extension.ts`
* `packages/cli/src/commands/add/codegen/add-codegen.ts`
* `packages/cli/src/commands/add/entity/add-entity.ts`
* `packages/cli/src/commands/add/job-queue/add-job-queue.ts`
* `packages/cli/src/commands/add/plugin/create-new-plugin.ts`
* `packages/cli/src/commands/add/service/add-service.ts`
* `packages/cli/src/commands/add/ui-extensions/add-ui-extensions.ts`
* `packages/cli/src/commands/migrate/migrate.ts`
* `packages/cli/src/commands/migrate/migration-operations.ts`
* `packages/cli/src/shared/command-registry.ts`
* `packages/cli/src/shared/shared-prompts.ts`
coderabbitai[bot] преди 7 месеца
родител
ревизия
77c874e354

+ 6 - 4
packages/cli/src/commands/add/add-operations.ts

@@ -40,10 +40,12 @@ export interface AddOperationResult {
 }
 
 /**
- * Determines which sub-command to execute based on the provided options and
- * delegates the work to that command's `run()` function. The interactive prompts
- * inside the sub-command will only be shown for data that is still missing – so
- * callers can supply as many or as few options as they need.
+ * Executes the appropriate "add" sub-command based on mutually exclusive options, delegating to the corresponding command handler.
+ *
+ * Accepts a set of options indicating which type of resource to add (e.g., plugin, entity, service, job queue, codegen config, API extension, or UI extensions) and invokes the relevant sub-command. Returns a result object indicating success or failure and a descriptive message. If required information is missing, sub-commands may prompt interactively for additional input.
+ *
+ * @param options - Options specifying which add operation to perform and any relevant parameters
+ * @returns The result of the add operation, including a success flag and message
  */
 export async function performAddOperation(options: AddOperationOptions): Promise<AddOperationResult> {
     try {

+ 17 - 0
packages/cli/src/commands/add/add.ts

@@ -18,6 +18,13 @@ const cancelledMessage = 'Add feature cancelled.';
 
 export interface AddOptions extends AddOperationOptions {}
 
+/**
+ * Executes the "add" command, enabling users to add features to a Vendure project in either interactive or non-interactive mode.
+ *
+ * If any options are provided, the command runs in non-interactive mode using those options; otherwise, it prompts the user interactively.
+ *
+ * @param options - Optional parameters to configure the add operation non-interactively
+ */
 export async function addCommand(options?: AddOptions) {
     // If any non-interactive option is supplied, we switch to the non-interactive path
     const nonInteractive = options && Object.values(options).some(v => v !== undefined && v !== false);
@@ -29,6 +36,11 @@ export async function addCommand(options?: AddOptions) {
     }
 }
 
+/**
+ * Executes the add operation in non-interactive mode using the provided options.
+ *
+ * Logs a success message if the operation completes successfully. On failure or exception, logs an error message (with stack trace for specific validation errors) and exits the process with status code 1.
+ */
 async function handleNonInteractiveMode(options: AddOperationOptions) {
     try {
         const result = await performAddOperation(options);
@@ -60,6 +72,11 @@ async function handleNonInteractiveMode(options: AddOperationOptions) {
     }
 }
 
+/**
+ * Guides the user through interactively adding a new feature to a Vendure project.
+ *
+ * Prompts the user to select a feature to add, executes the corresponding command, organizes imports if source files are modified, and provides feedback on completion or errors.
+ */
 async function handleInteractiveMode() {
     // eslint-disable-next-line no-console
     console.log(`\n`);

+ 9 - 0
packages/cli/src/commands/add/api-extension/add-api-extension.ts

@@ -47,6 +47,15 @@ export const addApiExtensionCommand = new CliCommand({
     run: options => addApiExtension(options),
 });
 
+/**
+ * Adds GraphQL API extensions to a Vendure plugin, supporting both interactive and non-interactive modes.
+ *
+ * In interactive mode, prompts the user to select a plugin and service, and to specify query and mutation names if needed. In non-interactive mode, requires all necessary options to be provided up front and does not allow interactive selection or creation of services.
+ *
+ * Generates resolver files and GraphQL schema definitions, registers the new API extensions with the selected plugin, and updates the relevant source files.
+ *
+ * @returns An object containing the updated project, the modified source files, and a reference to the affected service.
+ */
 async function addApiExtension(
     options?: AddApiExtensionOptions,
 ): Promise<CliCommandReturnVal<{ serviceRef: ServiceRef }>> {

+ 8 - 0
packages/cli/src/commands/add/codegen/add-codegen.ts

@@ -25,6 +25,14 @@ export const addCodegenCommand = new CliCommand({
     run: addCodegen,
 });
 
+/**
+ * Sets up GraphQL code generation for one or more Vendure plugins in the current project.
+ *
+ * Installs required codegen dependencies, generates a codegen configuration file, and adds a `codegen` script to `package.json`. Supports both interactive and non-interactive modes, allowing plugin selection by reference or name. If a plugin has UI extensions, configures additional client codegen entries. Throws errors if required plugins are not found or if the project root or `package.json` cannot be located.
+ *
+ * @param options - Optional settings for plugin selection, config file location, and non-interactive mode
+ * @returns An object containing the updated project and the generated codegen configuration source file
+ */
 async function addCodegen(options?: AddCodegenOptions): Promise<CliCommandReturnVal> {
     const providedVendurePlugin = options?.plugin;
     const { project } = await analyzeProject({

+ 14 - 0
packages/cli/src/commands/add/entity/add-entity.ts

@@ -35,6 +35,13 @@ export const addEntityCommand = new CliCommand({
     run: options => addEntity(options),
 });
 
+/**
+ * Adds a new entity to a Vendure plugin, supporting both interactive and non-interactive CLI modes.
+ *
+ * If required options are not provided in non-interactive mode, an error is thrown. The function generates entity and translation files as needed, updates the plugin source, and saves project changes.
+ *
+ * @returns An object containing the updated project, modified source files, and a reference to the newly created entity.
+ */
 async function addEntity(
     options?: Partial<AddEntityOptions>,
 ): Promise<CliCommandReturnVal<{ entityRef: EntityRef }>> {
@@ -82,6 +89,13 @@ async function addEntity(
     };
 }
 
+/**
+ * Determines the feature flags for a new entity, either from provided options or by prompting the user.
+ *
+ * If features are specified in the options, returns them directly. In non-interactive mode with a class name but no features, defaults to enabling custom fields and disabling translatable properties. Otherwise, prompts the user to select features interactively.
+ *
+ * @returns An object indicating whether custom fields and translatable properties are enabled for the entity.
+ */
 async function getFeatures(options?: Partial<AddEntityOptions>): Promise<AddEntityOptions['features']> {
     if (options?.features) {
         return options?.features;

+ 7 - 0
packages/cli/src/commands/add/job-queue/add-job-queue.ts

@@ -26,6 +26,13 @@ export const addJobQueueCommand = new CliCommand({
     run: options => addJobQueue(options),
 });
 
+/**
+ * Adds a new job queue to a Vendure plugin service, supporting both interactive and non-interactive CLI modes.
+ *
+ * In interactive mode, prompts the user to select a plugin, service, and job queue name. In non-interactive mode, requires explicit specification of the plugin, service, and job queue name via options. Modifies the selected service to inject the job queue, add necessary imports, implement `OnModuleInit`, and provide a trigger method for the new queue.
+ *
+ * @returns An object containing the updated project, modified source files, and a reference to the modified service.
+ */
 async function addJobQueue(
     options?: AddJobQueueOptions,
 ): Promise<CliCommandReturnVal<{ serviceRef: ServiceRef }>> {

+ 8 - 0
packages/cli/src/commands/add/plugin/create-new-plugin.ts

@@ -28,6 +28,14 @@ export const createNewPluginCommand = new CliCommand({
 
 const cancelledMessage = 'Plugin setup cancelled.';
 
+/**
+ * Creates a new Vendure plugin in the current project, supporting both interactive and non-interactive modes.
+ *
+ * If run interactively, prompts the user for the plugin name, directory, and optional additional features to scaffold. In non-interactive mode, uses provided options and throws errors for invalid input or existing directories. Integrates the new plugin into the Vendure config and optionally scaffolds additional features such as entities, services, or API extensions.
+ *
+ * @param options - Optional plugin generation options. If `name` is provided, runs non-interactively.
+ * @returns An object containing the updated project and a list of modified source files (empty if non-interactive or after completion).
+ */
 export async function createNewPlugin(
     options: Partial<GeneratePluginOptions> = {},
 ): Promise<CliCommandReturnVal> {

+ 8 - 0
packages/cli/src/commands/add/service/add-service.ts

@@ -35,6 +35,14 @@ export const addServiceCommand = new CliCommand({
     run: options => addService(options),
 });
 
+/**
+ * Adds a new service to a Vendure plugin, supporting both basic and entity-based services.
+ *
+ * Depending on the provided options and interactive prompts, generates a service file, customizes it for the selected entity if applicable, registers the service with the plugin, and saves all changes to the project. In non-interactive mode, requires explicit plugin and service name inputs.
+ *
+ * @param providedOptions - Optional configuration for service creation, including plugin, service type, service name, entity reference, config, and non-interactive mode flag.
+ * @returns An object containing the updated project, modified source files, and a reference to the newly created service.
+ */
 async function addService(
     providedOptions?: Partial<AddServiceOptions>,
 ): Promise<CliCommandReturnVal<{ serviceRef: ServiceRef }>> {

+ 8 - 0
packages/cli/src/commands/add/ui-extensions/add-ui-extensions.ts

@@ -26,6 +26,14 @@ export const addUiExtensionsCommand = new CliCommand<AddUiExtensionsOptions>({
     run: options => addUiExtensions(options),
 });
 
+/**
+ * Sets up Admin UI extensions for a specified Vendure plugin within the current project.
+ *
+ * Optionally operates in non-interactive mode, supports plugin selection by name or reference, and allows specifying a custom Vendure config file. Installs required dependencies, scaffolds UI extension files, updates the plugin class, and attempts to update the Vendure configuration to register the new UI extension. Returns the updated project and the modified plugin source file.
+ *
+ * @param options - Optional settings for plugin selection, config file path, and interactivity mode
+ * @returns An object containing the updated project and the modified plugin source file
+ */
 async function addUiExtensions(options?: AddUiExtensionsOptions): Promise<CliCommandReturnVal> {
     const providedVendurePlugin = options?.plugin;
     const { project } = await analyzeProject({ providedVendurePlugin, config: options?.config });

+ 17 - 3
packages/cli/src/commands/migrate/migrate.ts

@@ -17,9 +17,11 @@ export interface MigrateOptions {
 }
 
 /**
- * This command is currently not exposed due to unresolved issues which I think are related to
- * peculiarities in loading ESM modules vs CommonJS modules. More time is needed to dig into
- * this before we expose this command in the cli.ts file.
+ * Executes the database migration command in either interactive or non-interactive mode.
+ *
+ * If migration options are provided, runs the corresponding migration operation without user prompts. Otherwise, launches an interactive prompt for the user to select a migration action.
+ *
+ * @param options - Optional migration operation parameters to enable non-interactive execution
  */
 export async function migrateCommand(options?: MigrateOptions) {
     // Check if any non-interactive options are provided
@@ -33,6 +35,13 @@ export async function migrateCommand(options?: MigrateOptions) {
     await handleInteractiveMode();
 }
 
+/**
+ * Executes migration operations in non-interactive mode based on the provided options.
+ *
+ * Depending on the options, this function generates a new migration, runs pending migrations, or reverts the last migration. Logs the outcome and exits the process with code 1 on failure.
+ *
+ * @param options - Migration operation options specifying which action to perform
+ */
 async function handleNonInteractiveMode(options: MigrateOptions) {
     try {
         process.env.VENDURE_RUNNING_IN_CLI = 'true';
@@ -79,6 +88,11 @@ async function handleNonInteractiveMode(options: MigrateOptions) {
     }
 }
 
+/**
+ * Launches an interactive CLI prompt for managing database migrations.
+ *
+ * Guides the user through generating, running, or reverting migrations based on their selection. Exits the process if the user cancels the prompt.
+ */
 async function handleInteractiveMode() {
     // eslint-disable-next-line no-console
     console.log(`\n`);

+ 32 - 0
packages/cli/src/commands/migrate/migration-operations.ts

@@ -20,6 +20,14 @@ export interface MigrationResult {
     migrationsRan?: string[];
 }
 
+/**
+ * Generates a new database migration for a Vendure project.
+ *
+ * Validates the project directory, migration name, and determines the appropriate output directory before generating the migration. Returns the result indicating success, a descriptive message, and the migration name if generated.
+ *
+ * @param options - Options to specify the migration name and output directory.
+ * @returns The result of the migration generation, including success status, message, and the migration name if applicable.
+ */
 export async function generateMigrationOperation(options: MigrationOptions = {}): Promise<MigrationResult> {
     try {
         // Check if we're in a proper Vendure project directory
@@ -76,6 +84,11 @@ export async function generateMigrationOperation(options: MigrationOptions = {})
     }
 }
 
+/**
+ * Executes all pending database migrations for the current Vendure project.
+ *
+ * @returns The result of the migration operation, including success status, a descriptive message, and a list of migrations that were run if applicable.
+ */
 export async function runMigrationsOperation(): Promise<MigrationResult> {
     try {
         // Check if we're in a proper Vendure project directory
@@ -112,6 +125,11 @@ export async function runMigrationsOperation(): Promise<MigrationResult> {
     }
 }
 
+/**
+ * Reverts the most recently applied database migration in the current Vendure project.
+ *
+ * @returns The result of the revert operation, including success status and a descriptive message.
+ */
 export async function revertMigrationOperation(): Promise<MigrationResult> {
     try {
         // Check if we're in a proper Vendure project directory
@@ -143,6 +161,13 @@ export async function revertMigrationOperation(): Promise<MigrationResult> {
     }
 }
 
+/**
+ * Determines whether the current working directory is a Vendure project.
+ *
+ * Checks for the presence of Vendure configuration files and Vendure dependencies in `package.json`.
+ *
+ * @returns `true` if the directory appears to be a Vendure project; otherwise, `false`.
+ */
 function isVendureProjectDirectory(): boolean {
     const cwd = process.cwd();
 
@@ -172,6 +197,13 @@ function isVendureProjectDirectory(): boolean {
     return false;
 }
 
+/**
+ * Returns possible directories where migration files may be located for the given Vendure configuration.
+ *
+ * The returned array includes directories derived from the migration paths in the configuration, any source file containing a class implementing `MigrationInterface`, and a default `../migrations` directory relative to the Vendure config file.
+ *
+ * @returns An array of normalized directory paths that may contain migration files.
+ */
 function getMigrationsDir(vendureConfigRef: VendureConfigRef, config: VendureConfig): string[] {
     const options: string[] = [];
     if (

+ 13 - 0
packages/cli/src/shared/command-registry.ts

@@ -2,6 +2,14 @@ import { Command } from 'commander';
 
 import { CliCommandDefinition, CliCommandOption } from './cli-command-definition';
 
+/**
+ * Registers CLI commands and their options with a Commander.js program instance.
+ *
+ * For each command definition, adds the command with its name, description, and asynchronous action handler. Options and sub-options are registered with appropriate descriptions and formatting.
+ *
+ * @param program - The Commander.js program instance to which commands will be added
+ * @param commands - An array of command definitions specifying names, descriptions, actions, and options
+ */
 export function registerCommands(program: Command, commands: CliCommandDefinition[]): void {
     commands.forEach(commandDef => {
         const command = program
@@ -32,6 +40,11 @@ export function registerCommands(program: Command, commands: CliCommandDefinitio
     });
 }
 
+/**
+ * Adds an option to a Commander command, formatting the option flags and value placeholders based on whether the option is required.
+ *
+ * If the option is not required and expects a value, angle brackets in the value placeholder are converted to square brackets to indicate optionality.
+ */
 function addOption(command: Command, option: CliCommandOption): void {
     const parts: string[] = [];
     if (option.short) {

+ 15 - 0
packages/cli/src/shared/shared-prompts.ts

@@ -10,6 +10,13 @@ import { EntityRef } from './entity-ref';
 import { ServiceRef } from './service-ref';
 import { VendurePluginRef } from './vendure-plugin-ref';
 
+/**
+ * Analyzes a TypeScript project and returns its `ts-morph` Project instance, the path to the `tsconfig` file, and an optional config string.
+ *
+ * If a `providedVendurePlugin` is supplied, uses its associated project; otherwise, prompts the user to select a `tsconfig` file and analyzes the project with the source directory as the root.
+ *
+ * @returns An object containing the `Project` instance, the `tsConfigPath` (if available), and the provided `config` option.
+ */
 export async function analyzeProject(options: {
     providedVendurePlugin?: VendurePluginRef;
     cancelledMessage?: string;
@@ -41,6 +48,14 @@ export async function analyzeProject(options: {
     return { project: project as Project, tsConfigPath, config: options.config };
 }
 
+/**
+ * Prompts the user to select a Vendure plugin class from the project.
+ *
+ * If no plugins are found, the process is cancelled and exited. Returns a `VendurePluginRef` wrapping the selected plugin class.
+ *
+ * @param cancelledMessage - The message to display if the selection is cancelled
+ * @returns A reference to the selected Vendure plugin class
+ */
 export async function selectPlugin(project: Project, cancelledMessage: string): Promise<VendurePluginRef> {
     const pluginClasses = getPluginClasses(project);
     if (pluginClasses.length === 0) {