From d53e5f0a952fe8d2a138ef97a1768f1c222c597b Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:44:11 +0000 Subject: [PATCH 1/7] feat(WOR-TSK-202): implement config types for Node.js bindings Implement comprehensive NAPI-compatible type definitions for config commands: Input Parameters: - ConfigShowParams: parameters for configShow command - ConfigValidateParams: parameters for configValidate command Configuration Structures: - ConfigData: main configuration container - ChangesetConfigInfo: changeset management settings - VersionConfigInfo: version resolution settings - DependencyConfigInfo: dependency propagation settings - UpgradeConfigInfo: upgrade detection settings - RegistryConfigInfo: NPM registry configuration - ScopedRegistryEntry: scoped registry mapping - BackupConfigInfo: backup and rollback settings - ChangelogConfigInfo: changelog generation settings - AuditConfigInfo: audit and health check settings - AuditSectionsConfigInfo: audit section flags - HealthScoreWeightsInfo: health score weights - GitConfigInfo: git integration settings - ExecuteConfigInfo: command execution settings Response Data: - ConfigShowData: loaded configuration response - ConfigValidateData: validation results response - ConfigValidationIssue: individual validation issue API Responses: - ConfigShowApiResponse: wrapper for configShow - ConfigValidateApiResponse: wrapper for configValidate Constants: - VALID_STRATEGIES, VALID_BUMP_TYPES, VALID_CHANGELOG_FORMATS - VALID_MONOREPO_MODES, VALID_SEVERITY_LEVELS All types include comprehensive documentation, Default implementations, builder methods, and proper NAPI attributes for TypeScript generation. --- crates/node/src/types/config.rs | 2315 ++++++++++++++++++++++++++++++- 1 file changed, 2293 insertions(+), 22 deletions(-) diff --git a/crates/node/src/types/config.rs b/crates/node/src/types/config.rs index 4f1c807c..364e7359 100644 --- a/crates/node/src/types/config.rs +++ b/crates/node/src/types/config.rs @@ -1,50 +1,2321 @@ -//! Config command type definitions. +//! Config command type definitions for Node.js bindings. //! //! # What //! -//! This module contains type definitions for config commands (show, validate), -//! including parameter structures and response data types. +//! This module defines all NAPI-compatible type structures for the config commands +//! (`configShow` and `configValidate`), including input parameters and response data +//! types. These types enable JavaScript and TypeScript consumers to interact with +//! workspace configuration in a type-safe manner. //! //! # How //! -//! Types are defined with `#[napi(object)]` attribute to be exposed as -//! JavaScript objects. The module provides: +//! Types are defined with the `#[napi(object)]` attribute to be automatically +//! exposed as JavaScript objects. The module provides: //! -//! - `ConfigShowParams`: Input parameters for the config show command -//! - `ConfigShowData`: Response data containing configuration details -//! - `ConfigValidateParams`: Input parameters for the config validate command -//! - `ConfigValidateData`: Response data containing validation results +//! - **Input Parameters**: +//! - `ConfigShowParams`: Parameters for the `configShow` command +//! - `ConfigValidateParams`: Parameters for the `configValidate` command +//! +//! - **Response Data**: +//! - `ConfigShowData`: Response containing the loaded configuration and its path +//! - `ConfigValidateData`: Response containing validation results +//! +//! - **Configuration Structures** (exposed as nested objects in responses): +//! - `ConfigData`: Main configuration container with all sections +//! - `ChangesetConfigInfo`: Changeset management configuration +//! - `VersionConfigInfo`: Version resolution configuration +//! - `DependencyConfigInfo`: Dependency propagation configuration +//! - `UpgradeConfigInfo`: Upgrade detection and application configuration +//! - `RegistryConfigInfo`: NPM registry configuration +//! - `BackupConfigInfo`: Backup and rollback configuration +//! - `ChangelogConfigInfo`: Changelog generation configuration +//! - `AuditConfigInfo`: Audit and health check configuration +//! - `GitConfigInfo`: Git integration configuration +//! - `ExecuteConfigInfo`: Command execution configuration +//! +//! - **Validation Types**: +//! - `ConfigValidationIssue`: Individual validation issue with severity +//! +//! All types implement `Clone`, `Debug`, and `Serialize` for flexibility in +//! testing and serialization scenarios. //! //! # Why //! //! The config commands allow users to inspect and validate the workspace -//! configuration (repo.config) programmatically. +//! configuration (`repo.config.json`, `repo.config.toml`, or `repo.config.yaml`) +//! programmatically. These types provide: +//! +//! - **Type safety**: Strong typing for JavaScript/TypeScript consumers +//! - **Documentation**: Self-documenting API through TypeScript definitions +//! - **Consistency**: Matches the CLI configuration structure for compatibility +//! - **Validation**: Enables parameter validation before CLI execution //! //! # Examples //! +//! ## TypeScript Usage +//! //! ```typescript //! import { configShow, configValidate } from '@websublime/workspace-tools'; +//! import type { ConfigShowParams, ConfigValidateParams } from '@websublime/workspace-tools'; //! //! // Show configuration -//! const showResult = await configShow({ root: '.' }); +//! const showParams: ConfigShowParams = { root: '.' }; +//! const showResult = await configShow(showParams); +//! //! if (showResult.success) { -//! console.log(`Strategy: ${showResult.data.strategy}`); -//! console.log(`Changeset path: ${showResult.data.changesetPath}`); +//! console.log(`Config loaded from: ${showResult.data.configPath}`); +//! console.log(`Versioning strategy: ${showResult.data.config.version.strategy}`); +//! console.log(`Changeset path: ${showResult.data.config.changeset.path}`); +//! +//! // Access nested configuration sections +//! const { changeset, version, dependency, execute } = showResult.data.config; +//! console.log(`Default bump type: ${version.defaultBump}`); +//! console.log(`Propagate dependencies: ${dependency.propagateDependencies}`); +//! console.log(`Execute timeout: ${execute.timeoutSecs}s`); //! } //! //! // Validate configuration -//! const validateResult = await configValidate({ root: '.' }); +//! const validateParams: ConfigValidateParams = { root: '.' }; +//! const validateResult = await configValidate(validateParams); +//! //! if (validateResult.success) { -//! console.log(`Valid: ${validateResult.data.valid}`); +//! console.log(`Configuration valid: ${validateResult.data.valid}`); +//! +//! if (validateResult.data.errors.length > 0) { +//! console.error('Errors:'); +//! for (const error of validateResult.data.errors) { +//! console.error(` [${error.severity}] ${error.message} (field: ${error.field})`); +//! } +//! } +//! //! if (validateResult.data.warnings.length > 0) { -//! console.log('Warnings:', validateResult.data.warnings); +//! console.warn('Warnings:'); +//! for (const warning of validateResult.data.warnings) { +//! console.warn(` [${warning.severity}] ${warning.message}`); +//! } //! } //! } //! ``` +//! +//! ## Rust Usage (Internal) +//! +//! ```rust,ignore +//! use sublime_node_tools::types::config::{ +//! ConfigShowParams, ConfigShowData, ConfigData, +//! ChangesetConfigInfo, VersionConfigInfo +//! }; +//! +//! // Creating params for validation +//! let params = ConfigShowParams::new(".".to_string()); +//! +//! // Constructing response data +//! let config_data = ConfigData::default(); +//! let show_data = ConfigShowData::new( +//! "repo.config.json".to_string(), +//! config_data, +//! ); +//! ``` + +use napi_derive::napi; +use serde::Serialize; + +use crate::error::ErrorInfo; + +// ============================================================================ +// Constants +// ============================================================================ + +/// Valid versioning strategy values. +/// +/// These are the allowed values for the `strategy` field in `VersionConfigInfo`. +// Allow dead_code - will be used in story 7.3 for validation +#[allow(dead_code)] +pub const VALID_STRATEGIES: [&str; 2] = ["independent", "unified"]; + +/// Valid bump type values. +/// +/// These are the allowed values for default bump type fields. +// Allow dead_code - will be used in story 7.3 for validation +#[allow(dead_code)] +pub const VALID_BUMP_TYPES: [&str; 4] = ["major", "minor", "patch", "none"]; + +/// Valid changelog format values. +/// +/// These are the allowed values for the `format` field in `ChangelogConfigInfo`. +// Allow dead_code - will be used in story 7.3 for validation +#[allow(dead_code)] +pub const VALID_CHANGELOG_FORMATS: [&str; 3] = + ["keep-a-changelog", "conventional-commits", "custom"]; + +/// Valid monorepo mode values. +/// +/// These are the allowed values for the `monorepoMode` field in `ChangelogConfigInfo`. +// Allow dead_code - will be used in story 7.3 for validation +#[allow(dead_code)] +pub const VALID_MONOREPO_MODES: [&str; 3] = ["per-package", "root", "both"]; + +/// Valid severity levels for validation issues. +/// +/// These are the allowed values for the `severity` field in `ConfigValidationIssue`. +// Allow dead_code - will be used in story 7.3 for validation +#[allow(dead_code)] +pub const VALID_SEVERITY_LEVELS: [&str; 3] = ["error", "warning", "info"]; + +// ============================================================================ +// Input Parameters +// ============================================================================ + +/// Input parameters for the `configShow` command. +/// +/// This structure defines the parameters that can be passed to the `configShow` +/// function from JavaScript/TypeScript. The root path is required, while +/// the config path is optional. +/// +/// # Fields +/// +/// - `root`: The workspace root directory path (required) +/// - `config_path`: Optional path to a custom configuration file +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigShowParams { +/// // Workspace root directory path +/// root: string; +/// // Optional custom config file path +/// configPath?: string; +/// } +/// ``` +/// +/// # Examples +/// +/// ```typescript +/// // Minimal params with just root +/// const params: ConfigShowParams = { root: '.' }; +/// +/// // With custom config path +/// const paramsWithConfig: ConfigShowParams = { +/// root: '/path/to/workspace', +/// configPath: '/path/to/custom/repo.config.json' +/// }; +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigShowParams { + /// Workspace root directory path. + /// + /// This is the absolute or relative path to the root of the workspace. + /// The configuration file will be searched for in this directory unless + /// a custom `configPath` is provided. + pub root: String, + + /// Optional custom configuration file path. + /// + /// If not provided, the command will search for configuration files + /// in standard locations (`repo.config.json`, `repo.config.toml`, + /// `repo.config.yaml`) within the workspace root. + #[napi(ts_type = "string | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub config_path: Option, +} + +/// Input parameters for the `configValidate` command. +/// +/// This structure defines the parameters that can be passed to the `configValidate` +/// function from JavaScript/TypeScript. The root path is required, while +/// the config path is optional. +/// +/// # Fields +/// +/// - `root`: The workspace root directory path (required) +/// - `config_path`: Optional path to a custom configuration file +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigValidateParams { +/// // Workspace root directory path +/// root: string; +/// // Optional custom config file path +/// configPath?: string; +/// } +/// ``` +/// +/// # Examples +/// +/// ```typescript +/// // Minimal params with just root +/// const params: ConfigValidateParams = { root: '.' }; +/// +/// // With custom config path +/// const paramsWithConfig: ConfigValidateParams = { +/// root: '/path/to/workspace', +/// configPath: '/path/to/custom/repo.config.json' +/// }; +/// ``` +// Allow dead_code - will be used in story 7.3 (configValidate command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigValidateParams { + /// Workspace root directory path. + /// + /// This is the absolute or relative path to the root of the workspace. + /// The configuration file will be searched for in this directory unless + /// a custom `configPath` is provided. + pub root: String, + + /// Optional custom configuration file path. + /// + /// If not provided, the command will search for configuration files + /// in standard locations (`repo.config.json`, `repo.config.toml`, + /// `repo.config.yaml`) within the workspace root. + #[napi(ts_type = "string | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub config_path: Option, +} + +// ============================================================================ +// Configuration Structures +// ============================================================================ + +/// Changeset configuration information. +/// +/// Contains settings for changeset management, including paths and +/// environment configuration. +/// +/// # Fields +/// +/// - `path`: Path to store active changesets +/// - `history_path`: Path to store archived changesets +/// - `available_environments`: List of valid environment names +/// - `default_environments`: Default environments for new changesets +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ChangesetConfigInfo { +/// // Path to store active changesets (default: ".changesets") +/// path: string; +/// // Path to store archived changesets +/// historyPath: string; +/// // List of valid environment names +/// availableEnvironments: string[]; +/// // Default environments for new changesets +/// defaultEnvironments: string[]; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ChangesetConfigInfo { + /// Path to store active changesets. + /// + /// This is the directory where pending changeset files are stored. + /// Default value is `.changesets`. + pub path: String, + + /// Path to store archived changesets. + /// + /// This is the directory where consumed changeset files are moved + /// after a version bump operation. Typically a subdirectory of `path`. + pub history_path: String, + + /// List of valid environment names. + /// + /// These are the environments that changesets can target. Common + /// examples include "production", "staging", "development". + pub available_environments: Vec, + + /// Default environments for new changesets. + /// + /// These environments are automatically assigned to new changesets + /// if not explicitly specified. + pub default_environments: Vec, +} + +/// Version configuration information. +/// +/// Contains settings for version resolution and management. +/// +/// # Fields +/// +/// - `strategy`: Versioning strategy ("independent" or "unified") +/// - `default_bump`: Default version bump type +/// - `snapshot_format`: Format template for snapshot versions +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface VersionConfigInfo { +/// // Versioning strategy: "independent" or "unified" +/// strategy: string; +/// // Default version bump type: "major", "minor", "patch", or "none" +/// defaultBump: string; +/// // Format template for snapshot versions +/// snapshotFormat: string; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct VersionConfigInfo { + /// Versioning strategy. + /// + /// Determines how package versions are managed: + /// - `"independent"`: Each package has its own version + /// - `"unified"`: All packages share the same version + pub strategy: String, + + /// Default version bump type. + /// + /// Used when no explicit bump type is specified: + /// - `"major"`: Breaking changes + /// - `"minor"`: New features + /// - `"patch"`: Bug fixes + /// - `"none"`: No version change + pub default_bump: String, + + /// Format template for snapshot versions. + /// + /// Template string for generating snapshot version identifiers. + /// Supports placeholders like `{version}`, `{branch}`, `{commit}`, + /// `{shortCommit}`, and `{timestamp}`. + pub snapshot_format: String, +} + +/// Dependency configuration information. +/// +/// Contains settings for dependency propagation during version bumps. +/// +/// # Fields +/// +/// - `propagation_bump`: Version bump type for dependency updates +/// - `propagate_dependencies`: Whether to propagate regular dependencies +/// - `propagate_dev_dependencies`: Whether to propagate dev dependencies +/// - `propagate_peer_dependencies`: Whether to propagate peer dependencies +/// - `max_depth`: Maximum propagation depth +/// - `fail_on_circular`: Whether to fail on circular dependencies +/// - `skip_workspace_protocol`: Skip workspace: protocol dependencies +/// - `skip_file_protocol`: Skip file: protocol dependencies +/// - `skip_link_protocol`: Skip link: protocol dependencies +/// - `skip_portal_protocol`: Skip portal: protocol dependencies +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface DependencyConfigInfo { +/// // Version bump type for dependency updates +/// propagationBump: string; +/// // Whether to propagate regular dependencies +/// propagateDependencies: boolean; +/// // Whether to propagate dev dependencies +/// propagateDevDependencies: boolean; +/// // Whether to propagate peer dependencies +/// propagatePeerDependencies: boolean; +/// // Maximum propagation depth +/// maxDepth: number; +/// // Whether to fail on circular dependencies +/// failOnCircular: boolean; +/// // Skip workspace: protocol dependencies +/// skipWorkspaceProtocol: boolean; +/// // Skip file: protocol dependencies +/// skipFileProtocol: boolean; +/// // Skip link: protocol dependencies +/// skipLinkProtocol: boolean; +/// // Skip portal: protocol dependencies +/// skipPortalProtocol: boolean; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +// Allow struct_excessive_bools - this matches the pkg crate's DependencyConfig structure +#[allow(dead_code, clippy::struct_excessive_bools)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct DependencyConfigInfo { + /// Version bump type for dependency updates. + /// + /// When a package is updated, this determines how dependent packages + /// have their versions bumped. Values: "major", "minor", "patch", "none". + pub propagation_bump: String, + + /// Whether to propagate regular dependencies. + /// + /// If `true`, packages that depend on updated packages will also + /// be considered for version updates. + pub propagate_dependencies: bool, + + /// Whether to propagate dev dependencies. + /// + /// If `true`, packages that have the updated package as a dev + /// dependency will also be considered for version updates. + pub propagate_dev_dependencies: bool, + + /// Whether to propagate peer dependencies. + /// + /// If `true`, packages that have the updated package as a peer + /// dependency will also be considered for version updates. + pub propagate_peer_dependencies: bool, + + /// Maximum propagation depth. + /// + /// Limits how deep dependency propagation can traverse the + /// dependency graph. Prevents excessive updates in large monorepos. + pub max_depth: u32, + + /// Whether to fail on circular dependencies. + /// + /// If `true`, the operation fails when circular dependencies are + /// detected. If `false`, circular dependencies are handled gracefully. + pub fail_on_circular: bool, + + /// Skip workspace: protocol dependencies. + /// + /// If `true`, dependencies using `workspace:` protocol are not + /// propagated. These are typically handled differently in monorepos. + pub skip_workspace_protocol: bool, + + /// Skip file: protocol dependencies. + /// + /// If `true`, dependencies using `file:` protocol are not propagated. + pub skip_file_protocol: bool, + + /// Skip link: protocol dependencies. + /// + /// If `true`, dependencies using `link:` protocol are not propagated. + pub skip_link_protocol: bool, + + /// Skip portal: protocol dependencies. + /// + /// If `true`, dependencies using `portal:` protocol are not propagated. + pub skip_portal_protocol: bool, +} + +/// Registry configuration information. +/// +/// Contains settings for NPM registry access. +/// +/// # Fields +/// +/// - `default_registry`: Default npm registry URL +/// - `scoped_registries`: Map of scopes to registry URLs +/// - `timeout_secs`: Request timeout in seconds +/// - `retry_attempts`: Number of retry attempts for failed requests +/// - `read_npmrc`: Whether to read .npmrc for registry configuration +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface RegistryConfigInfo { +/// // Default npm registry URL +/// defaultRegistry: string; +/// // Map of scopes to registry URLs (e.g., {"@myorg": "https://npm.myorg.com"}) +/// scopedRegistries: Record; +/// // Request timeout in seconds +/// timeoutSecs: number; +/// // Number of retry attempts for failed requests +/// retryAttempts: number; +/// // Whether to read .npmrc for registry configuration +/// readNpmrc: boolean; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct RegistryConfigInfo { + /// Default npm registry URL. + /// + /// The registry URL to use for packages without a specific scope + /// configuration. Default is "https://registry.npmjs.org". + pub default_registry: String, + + /// Map of scopes to registry URLs. + /// + /// Allows configuring different registries for different npm scopes. + /// Keys are scope names (e.g., "@myorg"), values are registry URLs. + #[napi(ts_type = "Record")] + pub scoped_registries: Vec, + + /// Request timeout in seconds. + /// + /// How long to wait for registry requests before timing out. + pub timeout_secs: u32, + + /// Number of retry attempts for failed requests. + /// + /// How many times to retry a failed registry request before giving up. + pub retry_attempts: u32, + + /// Whether to read .npmrc for registry configuration. + /// + /// If `true`, the tool will read `.npmrc` files for additional + /// registry configuration and authentication tokens. + pub read_npmrc: bool, +} + +/// Scoped registry entry. +/// +/// Represents a mapping from an npm scope to a registry URL. +/// +/// # Fields +/// +/// - `scope`: The npm scope (e.g., "@myorg") +/// - `registry`: The registry URL for this scope +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ScopedRegistryEntry { +/// // The npm scope (e.g., "@myorg") +/// scope: string; +/// // The registry URL for this scope +/// registry: string; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ScopedRegistryEntry { + /// The npm scope. + /// + /// The scope name including the `@` prefix (e.g., "@myorg"). + pub scope: String, + + /// The registry URL for this scope. + /// + /// The full URL of the npm registry to use for this scope. + pub registry: String, +} + +/// Backup configuration information. +/// +/// Contains settings for backup and rollback functionality. +/// +/// # Fields +/// +/// - `enabled`: Whether backup is enabled +/// - `path`: Path to store backups +/// - `keep_count`: Number of backups to keep +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface BackupConfigInfo { +/// // Whether backup is enabled +/// enabled: boolean; +/// // Path to store backups +/// path: string; +/// // Number of backups to keep +/// keepCount: number; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct BackupConfigInfo { + /// Whether backup is enabled. + /// + /// If `true`, backups are created before operations that modify + /// package files, allowing rollback if needed. + pub enabled: bool, + + /// Path to store backups. + /// + /// The directory where backup files are stored. This should be + /// outside the workspace to avoid being affected by operations. + pub path: String, + + /// Number of backups to keep. + /// + /// Older backups beyond this count are automatically deleted. + pub keep_count: u32, +} + +/// Upgrade configuration information. +/// +/// Contains settings for upgrade detection and application. +/// +/// # Fields +/// +/// - `auto_changeset`: Automatically create changesets for upgrades +/// - `changeset_bump`: Version bump type for upgrade changesets +/// - `registry`: Registry configuration +/// - `backup`: Backup configuration +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface UpgradeConfigInfo { +/// // Automatically create changesets for upgrades +/// autoChangeset: boolean; +/// // Version bump type for upgrade changesets +/// changesetBump: string; +/// // Registry configuration +/// registry: RegistryConfigInfo; +/// // Backup configuration +/// backup: BackupConfigInfo; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct UpgradeConfigInfo { + /// Automatically create changesets for upgrades. + /// + /// If `true`, a changeset is automatically created when + /// dependency upgrades are applied. + pub auto_changeset: bool, + + /// Version bump type for upgrade changesets. + /// + /// The bump type to use when creating changesets for upgrades. + /// Values: "major", "minor", "patch", "none". + pub changeset_bump: String, + + /// Registry configuration. + /// + /// Settings for accessing npm registries to check for updates. + pub registry: RegistryConfigInfo, + + /// Backup configuration. + /// + /// Settings for backup and rollback functionality. + pub backup: BackupConfigInfo, +} + +/// Changelog configuration information. +/// +/// Contains settings for changelog generation. +/// +/// # Fields +/// +/// - `enabled`: Whether changelog generation is enabled +/// - `format`: Changelog format ("keep-a-changelog", "conventional-commits", "custom") +/// - `include_commit_links`: Whether to include commit links +/// - `repository_url`: Repository URL for generating links +/// - `conventional`: Whether to use conventional commits parsing +/// - `template`: Custom template path +/// - `exclude`: Patterns to exclude from changelog +/// - `monorepo_mode`: How to handle changelogs in monorepos +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ChangelogConfigInfo { +/// // Whether changelog generation is enabled +/// enabled: boolean; +/// // Changelog format: "keep-a-changelog", "conventional-commits", or "custom" +/// format: string; +/// // Whether to include commit links +/// includeCommitLinks: boolean; +/// // Repository URL for generating links +/// repositoryUrl?: string; +/// // Whether to use conventional commits parsing +/// conventional: boolean; +/// // Custom template path +/// template?: string; +/// // Patterns to exclude from changelog +/// exclude: string[]; +/// // How to handle changelogs in monorepos: "per-package", "root", or "both" +/// monorepoMode: string; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ChangelogConfigInfo { + /// Whether changelog generation is enabled. + /// + /// If `false`, no changelog files are generated or updated. + pub enabled: bool, + + /// Changelog format. + /// + /// The format to use for changelog entries: + /// - `"keep-a-changelog"`: Keep a Changelog format + /// - `"conventional-commits"`: Conventional Commits format + /// - `"custom"`: Custom template-based format + pub format: String, + + /// Whether to include commit links. + /// + /// If `true`, changelog entries include links to the relevant commits. + pub include_commit_links: bool, + + /// Repository URL for generating links. + /// + /// Used to generate links to commits, comparisons, and issues + /// in the changelog. Example: "https://github.com/org/repo". + #[napi(ts_type = "string | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub repository_url: Option, + + /// Whether to use conventional commits parsing. + /// + /// If `true`, commit messages are parsed using conventional commits + /// specification to categorize changes. + pub conventional: bool, + + /// Custom template path. + /// + /// Path to a custom template file for changelog generation. + /// Only used when `format` is `"custom"`. + #[napi(ts_type = "string | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub template: Option, + + /// Patterns to exclude from changelog. + /// + /// Commit messages or files matching these patterns are excluded + /// from changelog generation. + pub exclude: Vec, + + /// How to handle changelogs in monorepos. + /// + /// Determines where changelog files are created: + /// - `"per-package"`: Each package has its own CHANGELOG.md + /// - `"root"`: Single CHANGELOG.md at the repository root + /// - `"both"`: Both per-package and root changelogs + pub monorepo_mode: String, +} + +/// Audit configuration information. +/// +/// Contains settings for audit and health check functionality. +/// +/// # Fields +/// +/// - `enabled`: Whether audit is enabled +/// - `min_severity`: Minimum severity level to report +/// - `sections`: Which audit sections to run +/// - `health_score_weights`: Weights for health score calculation +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface AuditConfigInfo { +/// // Whether audit is enabled +/// enabled: boolean; +/// // Minimum severity level to report: "critical", "high", "medium", "low", "info" +/// minSeverity: string; +/// // Which audit sections to run +/// sections: AuditSectionsConfigInfo; +/// // Weights for health score calculation +/// healthScoreWeights: HealthScoreWeightsInfo; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct AuditConfigInfo { + /// Whether audit is enabled. + /// + /// If `false`, audit commands are skipped. + pub enabled: bool, + + /// Minimum severity level to report. + /// + /// Only issues at or above this severity are reported: + /// - `"critical"`: Only critical issues + /// - `"high"`: High and above + /// - `"medium"`: Medium and above + /// - `"low"`: Low and above + /// - `"info"`: All issues including informational + pub min_severity: String, + + /// Which audit sections to run. + /// + /// Allows selectively enabling or disabling specific audit checks. + pub sections: AuditSectionsConfigInfo, + + /// Weights for health score calculation. + /// + /// Determines how different factors contribute to the overall + /// health score. + pub health_score_weights: HealthScoreWeightsInfo, +} + +/// Audit sections configuration. +/// +/// Contains flags for enabling/disabling specific audit sections. +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface AuditSectionsConfigInfo { +/// // Check for available upgrades +/// upgrades: boolean; +/// // Analyze dependencies +/// dependencies: boolean; +/// // Check version consistency +/// versionConsistency: boolean; +/// // Detect breaking changes +/// breakingChanges: boolean; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +// Allow struct_excessive_bools - this matches the pkg crate's AuditConfig structure +#[allow(dead_code, clippy::struct_excessive_bools)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct AuditSectionsConfigInfo { + /// Check for available upgrades. + /// + /// Analyzes dependencies for available updates. + pub upgrades: bool, + + /// Analyze dependencies. + /// + /// Checks for circular dependencies, missing dependencies, etc. + pub dependencies: bool, + + /// Check version consistency. + /// + /// Verifies that dependency versions are consistent across packages. + pub version_consistency: bool, + + /// Detect breaking changes. + /// + /// Identifies potential breaking changes based on commits and changelogs. + pub breaking_changes: bool, +} + +/// Health score weights configuration. +/// +/// Contains weights for calculating the overall health score. +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface HealthScoreWeightsInfo { +/// // Weight for upgrade score (0.0-1.0) +/// upgradesWeight: number; +/// // Weight for dependencies score (0.0-1.0) +/// dependenciesWeight: number; +/// // Weight for version consistency score (0.0-1.0) +/// versionConsistencyWeight: number; +/// // Weight for breaking changes score (0.0-1.0) +/// breakingChangesWeight: number; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +// Allow struct_field_names - the _weight suffix is intentional for clarity in JavaScript +#[allow(dead_code, clippy::struct_field_names)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct HealthScoreWeightsInfo { + /// Weight for upgrade score. + /// + /// How much the upgrade status contributes to the health score. + /// Value between 0.0 and 1.0. + pub upgrades_weight: f64, + + /// Weight for dependencies score. + /// + /// How much the dependency health contributes to the health score. + /// Value between 0.0 and 1.0. + pub dependencies_weight: f64, + + /// Weight for version consistency score. + /// + /// How much version consistency contributes to the health score. + /// Value between 0.0 and 1.0. + pub version_consistency_weight: f64, + + /// Weight for breaking changes score. + /// + /// How much breaking changes impact the health score. + /// Value between 0.0 and 1.0. + pub breaking_changes_weight: f64, +} + +/// Git configuration information. +/// +/// Contains settings for Git integration. +/// +/// # Fields +/// +/// - `branch_base`: Base branch for comparisons +/// - `detect_affected_packages`: Whether to auto-detect affected packages +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface GitConfigInfo { +/// // Base branch for comparisons (e.g., "main", "master") +/// branchBase: string; +/// // Whether to auto-detect affected packages from Git changes +/// detectAffectedPackages: boolean; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct GitConfigInfo { + /// Base branch for comparisons. + /// + /// The branch used as the base for determining changes. + /// Common values: "main", "master", "develop". + pub branch_base: String, + + /// Whether to auto-detect affected packages. + /// + /// If `true`, packages affected by Git changes are automatically + /// detected based on file changes. + pub detect_affected_packages: bool, +} + +/// Execute configuration information. +/// +/// Contains settings for command execution with timeout and parallelism. +/// +/// # Fields +/// +/// - `timeout_secs`: Overall timeout in seconds +/// - `per_package_timeout_secs`: Per-package timeout in seconds +/// - `max_parallel`: Maximum number of parallel executions +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ExecuteConfigInfo { +/// // Overall timeout in seconds (0 = no timeout) +/// timeoutSecs: number; +/// // Per-package timeout in seconds (0 = no timeout) +/// perPackageTimeoutSecs: number; +/// // Maximum number of parallel executions +/// maxParallel: number; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ExecuteConfigInfo { + /// Overall timeout in seconds. + /// + /// Maximum time allowed for the entire execute command. + /// A value of 0 means no timeout. + pub timeout_secs: u32, + + /// Per-package timeout in seconds. + /// + /// Maximum time allowed for executing the command on each package. + /// A value of 0 means no timeout. + pub per_package_timeout_secs: u32, + + /// Maximum number of parallel executions. + /// + /// How many packages can have commands running simultaneously. + /// Higher values can speed up execution but increase resource usage. + pub max_parallel: u32, +} + +/// Main configuration data structure. +/// +/// Contains all configuration sections from the `repo.config` file. +/// This is the root structure that holds all workspace tool settings. +/// +/// # Fields +/// +/// - `changeset`: Changeset management configuration +/// - `version`: Version resolution configuration +/// - `dependency`: Dependency propagation configuration +/// - `upgrade`: Upgrade detection and application configuration +/// - `changelog`: Changelog generation configuration +/// - `audit`: Audit and health check configuration +/// - `git`: Git integration configuration +/// - `execute`: Command execution configuration +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigData { +/// // Changeset management configuration +/// changeset: ChangesetConfigInfo; +/// // Version resolution configuration +/// version: VersionConfigInfo; +/// // Dependency propagation configuration +/// dependency: DependencyConfigInfo; +/// // Upgrade detection and application configuration +/// upgrade: UpgradeConfigInfo; +/// // Changelog generation configuration +/// changelog: ChangelogConfigInfo; +/// // Audit and health check configuration +/// audit: AuditConfigInfo; +/// // Git integration configuration +/// git: GitConfigInfo; +/// // Command execution configuration +/// execute: ExecuteConfigInfo; +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize, Default)] +pub struct ConfigData { + /// Changeset management configuration. + /// + /// Settings for managing changesets including paths and environments. + pub changeset: ChangesetConfigInfo, + + /// Version resolution configuration. + /// + /// Settings for version management including strategy and defaults. + pub version: VersionConfigInfo, + + /// Dependency propagation configuration. + /// + /// Settings for how dependency updates propagate through the workspace. + pub dependency: DependencyConfigInfo, + + /// Upgrade detection and application configuration. + /// + /// Settings for checking and applying dependency upgrades. + pub upgrade: UpgradeConfigInfo, + + /// Changelog generation configuration. + /// + /// Settings for generating and formatting changelog files. + pub changelog: ChangelogConfigInfo, + + /// Audit and health check configuration. + /// + /// Settings for workspace health auditing. + pub audit: AuditConfigInfo, + + /// Git integration configuration. + /// + /// Settings for Git-related operations. + pub git: GitConfigInfo, + + /// Command execution configuration. + /// + /// Settings for running commands across packages. + pub execute: ExecuteConfigInfo, +} + +// ============================================================================ +// Response Data Types +// ============================================================================ + +/// Response data for the `configShow` command. +/// +/// Contains the loaded configuration and the path where it was found. +/// +/// # Fields +/// +/// - `config_path`: Path to the loaded configuration file +/// - `config_format`: Format of the configuration file (json, toml, yaml) +/// - `config`: The loaded configuration data +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigShowData { +/// // Path to the loaded configuration file +/// configPath: string; +/// // Format of the configuration file +/// configFormat: string; +/// // The loaded configuration data +/// config: ConfigData; +/// } +/// ``` +/// +/// # Examples +/// +/// ```typescript +/// const result = await configShow({ root: '.' }); +/// if (result.success) { +/// console.log(`Loaded from: ${result.data.configPath}`); +/// console.log(`Format: ${result.data.configFormat}`); +/// console.log(`Strategy: ${result.data.config.version.strategy}`); +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigShowData { + /// Path to the loaded configuration file. + /// + /// The absolute or relative path where the configuration was found. + /// Examples: "repo.config.json", "/path/to/repo.config.toml". + pub config_path: String, + + /// Format of the configuration file. + /// + /// The detected format based on file extension: + /// - `"json"`: JSON format + /// - `"toml"`: TOML format + /// - `"yaml"`: YAML format + pub config_format: String, + + /// The loaded configuration data. + /// + /// Contains all configuration sections parsed from the file. + pub config: ConfigData, +} + +/// Validation issue information. +/// +/// Represents a single validation issue found during configuration validation. +/// +/// # Fields +/// +/// - `severity`: Issue severity ("error", "warning", or "info") +/// - `field`: The configuration field with the issue +/// - `message`: Human-readable description of the issue +/// - `suggestion`: Optional suggestion for fixing the issue +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigValidationIssue { +/// // Issue severity: "error", "warning", or "info" +/// severity: string; +/// // The configuration field with the issue +/// field: string; +/// // Human-readable description of the issue +/// message: string; +/// // Optional suggestion for fixing the issue +/// suggestion?: string; +/// } +/// ``` +// Allow dead_code - will be used in story 7.3 (configValidate command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigValidationIssue { + /// Issue severity. + /// + /// Indicates the importance of the issue: + /// - `"error"`: Critical issue that must be fixed + /// - `"warning"`: Potential problem that should be addressed + /// - `"info"`: Informational note for improvement + pub severity: String, + + /// The configuration field with the issue. + /// + /// Dot-notation path to the field, e.g., "version.strategy" or + /// "changeset.path". + pub field: String, + + /// Human-readable description of the issue. + /// + /// Explains what is wrong with the configuration. + pub message: String, + + /// Optional suggestion for fixing the issue. + /// + /// Provides guidance on how to resolve the issue. + #[napi(ts_type = "string | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub suggestion: Option, +} + +/// Response data for the `configValidate` command. +/// +/// Contains validation results including whether the configuration is valid +/// and any issues found. +/// +/// # Fields +/// +/// - `valid`: Whether the configuration is valid (no errors) +/// - `config_path`: Path to the validated configuration file +/// - `errors`: List of validation errors +/// - `warnings`: List of validation warnings +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigValidateData { +/// // Whether the configuration is valid (no errors) +/// valid: boolean; +/// // Path to the validated configuration file +/// configPath: string; +/// // List of validation errors +/// errors: ConfigValidationIssue[]; +/// // List of validation warnings +/// warnings: ConfigValidationIssue[]; +/// } +/// ``` +/// +/// # Examples +/// +/// ```typescript +/// const result = await configValidate({ root: '.' }); +/// if (result.success) { +/// if (result.data.valid) { +/// console.log('Configuration is valid!'); +/// } else { +/// console.error(`Found ${result.data.errors.length} errors`); +/// for (const error of result.data.errors) { +/// console.error(` - [${error.field}]: ${error.message}`); +/// } +/// } +/// } +/// ``` +// Allow dead_code - will be used in story 7.3 (configValidate command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigValidateData { + /// Whether the configuration is valid. + /// + /// `true` if no errors were found (warnings are allowed), + /// `false` if there are any validation errors. + pub valid: bool, + + /// Path to the validated configuration file. + /// + /// The path where the configuration file was found and validated. + pub config_path: String, + + /// List of validation errors. + /// + /// Critical issues that must be fixed for the configuration to be valid. + pub errors: Vec, + + /// List of validation warnings. + /// + /// Non-critical issues that should be addressed but don't prevent + /// the configuration from being used. + pub warnings: Vec, +} + +// ============================================================================ +// API Response Types +// ============================================================================ + +/// API response wrapper for the `configShow` command. +/// +/// This structure wraps the `configShow` response with success/failure status +/// and consistent error handling, following the pattern used across all +/// NAPI commands. +/// +/// # Fields +/// +/// - `success`: Whether the operation succeeded +/// - `data`: The config show data (present when success is true) +/// - `error`: Error information (present when success is false) +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigShowApiResponse { +/// // Whether the operation succeeded +/// success: boolean; +/// // The config show data (present when success is true) +/// data?: ConfigShowData; +/// // Error information (present when success is false) +/// error?: ErrorInfo; +/// } +/// ``` +/// +/// # Examples +/// +/// ```typescript +/// const result = await configShow({ root: '.' }); +/// +/// if (result.success) { +/// // result.data is ConfigShowData +/// console.log(result.data.config.version.strategy); +/// } else { +/// // result.error is ErrorInfo +/// console.error(`[${result.error.code}] ${result.error.message}`); +/// } +/// ``` +// Allow dead_code - will be used in story 7.2 (configShow command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigShowApiResponse { + /// Whether the operation succeeded. + /// + /// - `true`: Operation completed successfully, `data` field will be present + /// - `false`: Operation failed, `error` field will be present + pub success: bool, + + /// The config show data (only present when `success` is `true`). + /// + /// Contains the loaded configuration and its path. + #[napi(ts_type = "ConfigShowData | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + + /// Error information (only present when `success` is `false`). + /// + /// Contains structured error information with a Node.js-style error code, + /// message, optional context, and error kind. + #[napi(ts_type = "ErrorInfo | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, +} + +/// API response wrapper for the `configValidate` command. +/// +/// This structure wraps the `configValidate` response with success/failure status +/// and consistent error handling, following the pattern used across all +/// NAPI commands. +/// +/// # Fields +/// +/// - `success`: Whether the operation succeeded +/// - `data`: The config validate data (present when success is true) +/// - `error`: Error information (present when success is false) +/// +/// # TypeScript Definition +/// +/// ```typescript +/// interface ConfigValidateApiResponse { +/// // Whether the operation succeeded +/// success: boolean; +/// // The config validate data (present when success is true) +/// data?: ConfigValidateData; +/// // Error information (present when success is false) +/// error?: ErrorInfo; +/// } +/// ``` +/// +/// # Examples +/// +/// ```typescript +/// const result = await configValidate({ root: '.' }); +/// +/// if (result.success) { +/// // result.data is ConfigValidateData +/// console.log(`Valid: ${result.data.valid}`); +/// console.log(`Errors: ${result.data.errors.length}`); +/// } else { +/// // result.error is ErrorInfo +/// console.error(`[${result.error.code}] ${result.error.message}`); +/// } +/// ``` +// Allow dead_code - will be used in story 7.3 (configValidate command) +#[allow(dead_code)] +#[napi(object)] +#[derive(Debug, Clone, Serialize)] +pub struct ConfigValidateApiResponse { + /// Whether the operation succeeded. + /// + /// - `true`: Operation completed successfully, `data` field will be present + /// - `false`: Operation failed, `error` field will be present + pub success: bool, + + /// The config validate data (only present when `success` is `true`). + /// + /// Contains validation results including whether the config is valid + /// and any issues found. + #[napi(ts_type = "ConfigValidateData | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, + + /// Error information (only present when `success` is `false`). + /// + /// Contains structured error information with a Node.js-style error code, + /// message, optional context, and error kind. + #[napi(ts_type = "ErrorInfo | undefined")] + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, +} + +// ============================================================================ +// Implementations +// ============================================================================ + +#[allow(dead_code)] +impl ConfigShowParams { + /// Creates a new `ConfigShowParams` with the specified root path. + /// + /// # Arguments + /// + /// * `root` - The workspace root directory path + /// + /// # Returns + /// + /// A new `ConfigShowParams` instance with default optional values. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::ConfigShowParams; + /// + /// let params = ConfigShowParams::new(".".to_string()); + /// assert_eq!(params.root, "."); + /// assert!(params.config_path.is_none()); + /// ``` + #[must_use] + pub fn new(root: String) -> Self { + Self { root, config_path: None } + } + + /// Creates a new `ConfigShowParams` with a custom config path. + /// + /// # Arguments + /// + /// * `root` - The workspace root directory path + /// * `config_path` - Custom configuration file path + /// + /// # Returns + /// + /// A new `ConfigShowParams` instance with the specified config path. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::ConfigShowParams; + /// + /// let params = ConfigShowParams::with_config( + /// ".".to_string(), + /// "custom/repo.config.json".to_string(), + /// ); + /// assert_eq!(params.config_path, Some("custom/repo.config.json".to_string())); + /// ``` + #[must_use] + pub fn with_config(root: String, config_path: String) -> Self { + Self { root, config_path: Some(config_path) } + } +} + +#[allow(dead_code)] +impl ConfigValidateParams { + /// Creates a new `ConfigValidateParams` with the specified root path. + /// + /// # Arguments + /// + /// * `root` - The workspace root directory path + /// + /// # Returns + /// + /// A new `ConfigValidateParams` instance with default optional values. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::ConfigValidateParams; + /// + /// let params = ConfigValidateParams::new(".".to_string()); + /// assert_eq!(params.root, "."); + /// assert!(params.config_path.is_none()); + /// ``` + #[must_use] + pub fn new(root: String) -> Self { + Self { root, config_path: None } + } + + /// Creates a new `ConfigValidateParams` with a custom config path. + /// + /// # Arguments + /// + /// * `root` - The workspace root directory path + /// * `config_path` - Custom configuration file path + /// + /// # Returns + /// + /// A new `ConfigValidateParams` instance with the specified config path. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::ConfigValidateParams; + /// + /// let params = ConfigValidateParams::with_config( + /// ".".to_string(), + /// "custom/repo.config.json".to_string(), + /// ); + /// assert_eq!(params.config_path, Some("custom/repo.config.json".to_string())); + /// ``` + #[must_use] + pub fn with_config(root: String, config_path: String) -> Self { + Self { root, config_path: Some(config_path) } + } +} + +#[allow(dead_code)] +impl ChangesetConfigInfo { + /// Creates a new `ChangesetConfigInfo` with the specified values. + /// + /// # Arguments + /// + /// * `path` - Path to store active changesets + /// * `history_path` - Path to store archived changesets + /// * `available_environments` - List of valid environment names + /// * `default_environments` - Default environments for new changesets + /// + /// # Returns + /// + /// A new `ChangesetConfigInfo` instance. + #[must_use] + pub fn new( + path: String, + history_path: String, + available_environments: Vec, + default_environments: Vec, + ) -> Self { + Self { path, history_path, available_environments, default_environments } + } +} + +#[allow(dead_code)] +impl Default for ChangesetConfigInfo { + fn default() -> Self { + Self { + path: ".changesets".to_string(), + history_path: ".changesets/history".to_string(), + available_environments: vec![], + default_environments: vec![], + } + } +} + +#[allow(dead_code)] +impl VersionConfigInfo { + /// Creates a new `VersionConfigInfo` with the specified values. + /// + /// # Arguments + /// + /// * `strategy` - Versioning strategy + /// * `default_bump` - Default version bump type + /// * `snapshot_format` - Format template for snapshot versions + /// + /// # Returns + /// + /// A new `VersionConfigInfo` instance. + #[must_use] + pub fn new(strategy: String, default_bump: String, snapshot_format: String) -> Self { + Self { strategy, default_bump, snapshot_format } + } +} + +#[allow(dead_code)] +impl Default for VersionConfigInfo { + fn default() -> Self { + Self { + strategy: "independent".to_string(), + default_bump: "patch".to_string(), + snapshot_format: "{version}-{branch}.{commit}".to_string(), + } + } +} + +#[allow(dead_code)] +impl DependencyConfigInfo { + /// Creates a new `DependencyConfigInfo` with the specified values. + #[must_use] + #[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)] + pub fn new( + propagation_bump: String, + propagate_dependencies: bool, + propagate_dev_dependencies: bool, + propagate_peer_dependencies: bool, + max_depth: u32, + fail_on_circular: bool, + skip_workspace_protocol: bool, + skip_file_protocol: bool, + skip_link_protocol: bool, + skip_portal_protocol: bool, + ) -> Self { + Self { + propagation_bump, + propagate_dependencies, + propagate_dev_dependencies, + propagate_peer_dependencies, + max_depth, + fail_on_circular, + skip_workspace_protocol, + skip_file_protocol, + skip_link_protocol, + skip_portal_protocol, + } + } +} + +#[allow(dead_code)] +impl Default for DependencyConfigInfo { + fn default() -> Self { + Self { + propagation_bump: "patch".to_string(), + propagate_dependencies: true, + propagate_dev_dependencies: false, + propagate_peer_dependencies: false, + max_depth: 10, + fail_on_circular: false, + skip_workspace_protocol: true, + skip_file_protocol: true, + skip_link_protocol: true, + skip_portal_protocol: true, + } + } +} + +#[allow(dead_code)] +impl RegistryConfigInfo { + /// Creates a new `RegistryConfigInfo` with the specified values. + #[must_use] + pub fn new( + default_registry: String, + scoped_registries: Vec, + timeout_secs: u32, + retry_attempts: u32, + read_npmrc: bool, + ) -> Self { + Self { default_registry, scoped_registries, timeout_secs, retry_attempts, read_npmrc } + } +} + +#[allow(dead_code)] +impl Default for RegistryConfigInfo { + fn default() -> Self { + Self { + default_registry: "https://registry.npmjs.org".to_string(), + scoped_registries: vec![], + timeout_secs: 30, + retry_attempts: 3, + read_npmrc: true, + } + } +} + +#[allow(dead_code)] +impl ScopedRegistryEntry { + /// Creates a new `ScopedRegistryEntry`. + #[must_use] + pub fn new(scope: String, registry: String) -> Self { + Self { scope, registry } + } +} + +#[allow(dead_code)] +impl BackupConfigInfo { + /// Creates a new `BackupConfigInfo` with the specified values. + #[must_use] + pub fn new(enabled: bool, path: String, keep_count: u32) -> Self { + Self { enabled, path, keep_count } + } +} + +#[allow(dead_code)] +impl Default for BackupConfigInfo { + fn default() -> Self { + Self { enabled: true, path: ".backups".to_string(), keep_count: 5 } + } +} + +#[allow(dead_code)] +impl UpgradeConfigInfo { + /// Creates a new `UpgradeConfigInfo` with the specified values. + #[must_use] + pub fn new( + auto_changeset: bool, + changeset_bump: String, + registry: RegistryConfigInfo, + backup: BackupConfigInfo, + ) -> Self { + Self { auto_changeset, changeset_bump, registry, backup } + } +} + +#[allow(dead_code)] +impl Default for UpgradeConfigInfo { + fn default() -> Self { + Self { + auto_changeset: true, + changeset_bump: "patch".to_string(), + registry: RegistryConfigInfo::default(), + backup: BackupConfigInfo::default(), + } + } +} + +#[allow(dead_code)] +impl ChangelogConfigInfo { + /// Creates a new `ChangelogConfigInfo` with the specified values. + #[must_use] + #[allow(clippy::too_many_arguments)] + pub fn new( + enabled: bool, + format: String, + include_commit_links: bool, + repository_url: Option, + conventional: bool, + template: Option, + exclude: Vec, + monorepo_mode: String, + ) -> Self { + Self { + enabled, + format, + include_commit_links, + repository_url, + conventional, + template, + exclude, + monorepo_mode, + } + } +} + +#[allow(dead_code)] +impl Default for ChangelogConfigInfo { + fn default() -> Self { + Self { + enabled: true, + format: "keep-a-changelog".to_string(), + include_commit_links: true, + repository_url: None, + conventional: true, + template: None, + exclude: vec![], + monorepo_mode: "per-package".to_string(), + } + } +} + +#[allow(dead_code)] +impl AuditSectionsConfigInfo { + /// Creates a new `AuditSectionsConfigInfo` with the specified values. + #[must_use] + #[allow(clippy::fn_params_excessive_bools)] + pub fn new( + upgrades: bool, + dependencies: bool, + version_consistency: bool, + breaking_changes: bool, + ) -> Self { + Self { upgrades, dependencies, version_consistency, breaking_changes } + } +} + +#[allow(dead_code)] +impl Default for AuditSectionsConfigInfo { + fn default() -> Self { + Self { + upgrades: true, + dependencies: true, + version_consistency: true, + breaking_changes: true, + } + } +} + +#[allow(dead_code)] +impl HealthScoreWeightsInfo { + /// Creates a new `HealthScoreWeightsInfo` with the specified values. + #[must_use] + pub fn new( + upgrades_weight: f64, + dependencies_weight: f64, + version_consistency_weight: f64, + breaking_changes_weight: f64, + ) -> Self { + Self { + upgrades_weight, + dependencies_weight, + version_consistency_weight, + breaking_changes_weight, + } + } +} + +#[allow(dead_code)] +impl Default for HealthScoreWeightsInfo { + fn default() -> Self { + Self { + upgrades_weight: 0.25, + dependencies_weight: 0.25, + version_consistency_weight: 0.25, + breaking_changes_weight: 0.25, + } + } +} + +#[allow(dead_code)] +impl AuditConfigInfo { + /// Creates a new `AuditConfigInfo` with the specified values. + #[must_use] + pub fn new( + enabled: bool, + min_severity: String, + sections: AuditSectionsConfigInfo, + health_score_weights: HealthScoreWeightsInfo, + ) -> Self { + Self { enabled, min_severity, sections, health_score_weights } + } +} + +#[allow(dead_code)] +impl Default for AuditConfigInfo { + fn default() -> Self { + Self { + enabled: true, + min_severity: "low".to_string(), + sections: AuditSectionsConfigInfo::default(), + health_score_weights: HealthScoreWeightsInfo::default(), + } + } +} + +#[allow(dead_code)] +impl GitConfigInfo { + /// Creates a new `GitConfigInfo` with the specified values. + #[must_use] + pub fn new(branch_base: String, detect_affected_packages: bool) -> Self { + Self { branch_base, detect_affected_packages } + } +} + +#[allow(dead_code)] +impl Default for GitConfigInfo { + fn default() -> Self { + Self { branch_base: "main".to_string(), detect_affected_packages: true } + } +} + +#[allow(dead_code)] +impl ExecuteConfigInfo { + /// Creates a new `ExecuteConfigInfo` with the specified values. + #[must_use] + pub fn new(timeout_secs: u32, per_package_timeout_secs: u32, max_parallel: u32) -> Self { + Self { timeout_secs, per_package_timeout_secs, max_parallel } + } +} + +#[allow(dead_code)] +impl Default for ExecuteConfigInfo { + fn default() -> Self { + Self { timeout_secs: 300, per_package_timeout_secs: 60, max_parallel: 4 } + } +} + +#[allow(dead_code)] +impl ConfigData { + /// Creates a new `ConfigData` with the specified values. + #[must_use] + #[allow(clippy::too_many_arguments)] + pub fn new( + changeset: ChangesetConfigInfo, + version: VersionConfigInfo, + dependency: DependencyConfigInfo, + upgrade: UpgradeConfigInfo, + changelog: ChangelogConfigInfo, + audit: AuditConfigInfo, + git: GitConfigInfo, + execute: ExecuteConfigInfo, + ) -> Self { + Self { changeset, version, dependency, upgrade, changelog, audit, git, execute } + } +} + +#[allow(dead_code)] +impl ConfigShowData { + /// Creates a new `ConfigShowData` with the specified values. + /// + /// # Arguments + /// + /// * `config_path` - Path to the loaded configuration file + /// * `config_format` - Format of the configuration file + /// * `config` - The loaded configuration data + /// + /// # Returns + /// + /// A new `ConfigShowData` instance. + #[must_use] + pub fn new(config_path: String, config_format: String, config: ConfigData) -> Self { + Self { config_path, config_format, config } + } +} + +#[allow(dead_code)] +impl ConfigValidationIssue { + /// Creates a new validation error. + /// + /// # Arguments + /// + /// * `field` - The configuration field with the issue + /// * `message` - Human-readable description of the issue + /// + /// # Returns + /// + /// A new `ConfigValidationIssue` with severity "error". + #[must_use] + pub fn error(field: String, message: String) -> Self { + Self { severity: "error".to_string(), field, message, suggestion: None } + } + + /// Creates a new validation error with a suggestion. + /// + /// # Arguments + /// + /// * `field` - The configuration field with the issue + /// * `message` - Human-readable description of the issue + /// * `suggestion` - Suggestion for fixing the issue + /// + /// # Returns + /// + /// A new `ConfigValidationIssue` with severity "error" and a suggestion. + #[must_use] + pub fn error_with_suggestion(field: String, message: String, suggestion: String) -> Self { + Self { severity: "error".to_string(), field, message, suggestion: Some(suggestion) } + } + + /// Creates a new validation warning. + /// + /// # Arguments + /// + /// * `field` - The configuration field with the issue + /// * `message` - Human-readable description of the issue + /// + /// # Returns + /// + /// A new `ConfigValidationIssue` with severity "warning". + #[must_use] + pub fn warning(field: String, message: String) -> Self { + Self { severity: "warning".to_string(), field, message, suggestion: None } + } + + /// Creates a new validation warning with a suggestion. + /// + /// # Arguments + /// + /// * `field` - The configuration field with the issue + /// * `message` - Human-readable description of the issue + /// * `suggestion` - Suggestion for fixing the issue + /// + /// # Returns + /// + /// A new `ConfigValidationIssue` with severity "warning" and a suggestion. + #[must_use] + pub fn warning_with_suggestion(field: String, message: String, suggestion: String) -> Self { + Self { severity: "warning".to_string(), field, message, suggestion: Some(suggestion) } + } + + /// Creates a new informational validation issue. + /// + /// # Arguments + /// + /// * `field` - The configuration field with the issue + /// * `message` - Human-readable description of the issue + /// + /// # Returns + /// + /// A new `ConfigValidationIssue` with severity "info". + #[must_use] + pub fn info(field: String, message: String) -> Self { + Self { severity: "info".to_string(), field, message, suggestion: None } + } + + /// Creates a new `ConfigValidationIssue` with all fields specified. + /// + /// # Arguments + /// + /// * `severity` - Issue severity ("error", "warning", or "info") + /// * `field` - The configuration field with the issue + /// * `message` - Human-readable description of the issue + /// * `suggestion` - Optional suggestion for fixing the issue + /// + /// # Returns + /// + /// A new `ConfigValidationIssue` instance. + #[must_use] + pub fn new( + severity: String, + field: String, + message: String, + suggestion: Option, + ) -> Self { + Self { severity, field, message, suggestion } + } + + /// Returns whether this issue is an error. + #[must_use] + pub fn is_error(&self) -> bool { + self.severity == "error" + } + + /// Returns whether this issue is a warning. + #[must_use] + pub fn is_warning(&self) -> bool { + self.severity == "warning" + } + + /// Returns whether this issue is informational. + #[must_use] + pub fn is_info(&self) -> bool { + self.severity == "info" + } +} + +#[allow(dead_code)] +impl ConfigValidateData { + /// Creates a new `ConfigValidateData` with the specified values. + /// + /// # Arguments + /// + /// * `valid` - Whether the configuration is valid + /// * `config_path` - Path to the validated configuration file + /// * `errors` - List of validation errors + /// * `warnings` - List of validation warnings + /// + /// # Returns + /// + /// A new `ConfigValidateData` instance. + #[must_use] + pub fn new( + valid: bool, + config_path: String, + errors: Vec, + warnings: Vec, + ) -> Self { + Self { valid, config_path, errors, warnings } + } + + /// Creates a valid configuration result. + /// + /// # Arguments + /// + /// * `config_path` - Path to the validated configuration file + /// + /// # Returns + /// + /// A new `ConfigValidateData` with `valid = true` and no errors or warnings. + #[must_use] + pub fn valid(config_path: String) -> Self { + Self { valid: true, config_path, errors: vec![], warnings: vec![] } + } + + /// Creates a valid configuration result with warnings. + /// + /// # Arguments + /// + /// * `config_path` - Path to the validated configuration file + /// * `warnings` - List of validation warnings + /// + /// # Returns + /// + /// A new `ConfigValidateData` with `valid = true` and the specified warnings. + #[must_use] + pub fn valid_with_warnings(config_path: String, warnings: Vec) -> Self { + Self { valid: true, config_path, errors: vec![], warnings } + } + + /// Creates an invalid configuration result. + /// + /// # Arguments + /// + /// * `config_path` - Path to the validated configuration file + /// * `errors` - List of validation errors + /// + /// # Returns + /// + /// A new `ConfigValidateData` with `valid = false` and the specified errors. + #[must_use] + pub fn invalid(config_path: String, errors: Vec) -> Self { + Self { valid: false, config_path, errors, warnings: vec![] } + } + + /// Creates an invalid configuration result with both errors and warnings. + /// + /// # Arguments + /// + /// * `config_path` - Path to the validated configuration file + /// * `errors` - List of validation errors + /// * `warnings` - List of validation warnings + /// + /// # Returns + /// + /// A new `ConfigValidateData` with `valid = false` and the specified issues. + #[must_use] + pub fn invalid_with_warnings( + config_path: String, + errors: Vec, + warnings: Vec, + ) -> Self { + Self { valid: false, config_path, errors, warnings } + } + + /// Returns the total number of issues (errors + warnings). + #[must_use] + pub fn total_issues(&self) -> usize { + self.errors.len() + self.warnings.len() + } + + /// Returns whether there are any errors. + #[must_use] + pub fn has_errors(&self) -> bool { + !self.errors.is_empty() + } + + /// Returns whether there are any warnings. + #[must_use] + pub fn has_warnings(&self) -> bool { + !self.warnings.is_empty() + } +} + +#[allow(dead_code)] +impl ConfigShowApiResponse { + /// Creates a successful config show response with data. + /// + /// # Arguments + /// + /// * `data` - The config show data to include + /// + /// # Returns + /// + /// A new `ConfigShowApiResponse` with `success = true` and the provided data. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::{ + /// ConfigShowApiResponse, ConfigShowData, ConfigData + /// }; + /// + /// let data = ConfigShowData::new( + /// "repo.config.json".to_string(), + /// "json".to_string(), + /// ConfigData::default(), + /// ); + /// let response = ConfigShowApiResponse::success(data); + /// assert!(response.success); + /// assert!(response.data.is_some()); + /// ``` + #[must_use] + pub fn success(data: ConfigShowData) -> Self { + Self { success: true, data: Some(data), error: None } + } + + /// Creates a failed config show response with error information. + /// + /// # Arguments + /// + /// * `error` - The error information to include + /// + /// # Returns + /// + /// A new `ConfigShowApiResponse` with `success = false` and the provided error. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::ConfigShowApiResponse; + /// use sublime_node_tools::error::ErrorInfo; + /// + /// let error = ErrorInfo::not_found("Config file not found", Some("repo.config.json")); + /// let response = ConfigShowApiResponse::failure(error); + /// assert!(!response.success); + /// assert!(response.error.is_some()); + /// ``` + #[must_use] + pub fn failure(error: ErrorInfo) -> Self { + Self { success: false, data: None, error: Some(error) } + } + + /// Returns whether this response represents a success. + /// + /// # Returns + /// + /// `true` if the operation succeeded, `false` otherwise. + #[must_use] + pub fn is_success(&self) -> bool { + self.success + } + + /// Returns whether this response represents a failure. + /// + /// # Returns + /// + /// `true` if the operation failed, `false` otherwise. + #[must_use] + pub fn is_failure(&self) -> bool { + !self.success + } +} + +#[allow(dead_code)] +impl ConfigValidateApiResponse { + /// Creates a successful config validate response with data. + /// + /// # Arguments + /// + /// * `data` - The config validate data to include + /// + /// # Returns + /// + /// A new `ConfigValidateApiResponse` with `success = true` and the provided data. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::{ + /// ConfigValidateApiResponse, ConfigValidateData + /// }; + /// + /// let data = ConfigValidateData::valid("repo.config.json".to_string()); + /// let response = ConfigValidateApiResponse::success(data); + /// assert!(response.success); + /// assert!(response.data.is_some()); + /// ``` + #[must_use] + pub fn success(data: ConfigValidateData) -> Self { + Self { success: true, data: Some(data), error: None } + } + + /// Creates a failed config validate response with error information. + /// + /// # Arguments + /// + /// * `error` - The error information to include + /// + /// # Returns + /// + /// A new `ConfigValidateApiResponse` with `success = false` and the provided error. + /// + /// # Examples + /// + /// ```rust,ignore + /// use sublime_node_tools::types::config::ConfigValidateApiResponse; + /// use sublime_node_tools::error::ErrorInfo; + /// + /// let error = ErrorInfo::not_found("Config file not found", Some("repo.config.json")); + /// let response = ConfigValidateApiResponse::failure(error); + /// assert!(!response.success); + /// assert!(response.error.is_some()); + /// ``` + #[must_use] + pub fn failure(error: ErrorInfo) -> Self { + Self { success: false, data: None, error: Some(error) } + } + + /// Returns whether this response represents a success. + /// + /// # Returns + /// + /// `true` if the operation succeeded, `false` otherwise. + #[must_use] + pub fn is_success(&self) -> bool { + self.success + } -// TODO: will be implemented on story 7.1 - Config Types -// This module will contain: -// - ConfigShowParams: { root: string } -// - ConfigShowData: { configPath, strategy, changesetPath, ... } -// - ConfigValidateParams: { root: string } -// - ConfigValidateData: { valid: boolean, errors: string[], warnings: string[] } + /// Returns whether this response represents a failure. + /// + /// # Returns + /// + /// `true` if the operation failed, `false` otherwise. + #[must_use] + pub fn is_failure(&self) -> bool { + !self.success + } +} From b6e8cb4c26effd5a0a01e05c899956b1fc45a1ae Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:44:19 +0000 Subject: [PATCH 2/7] feat(WOR-TSK-202): export config types from types module Update types/mod.rs to export all config types: - ConfigShowParams, ConfigValidateParams - ConfigShowData, ConfigValidateData - ConfigShowApiResponse, ConfigValidateApiResponse - ConfigValidationIssue, ConfigData - All configuration section types (ChangesetConfigInfo, etc.) - Validation constants Types are marked with allow(unused_imports) as they will be used in stories 7.2-7.3 (config commands implementation). --- crates/node/src/types/mod.rs | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/node/src/types/mod.rs b/crates/node/src/types/mod.rs index cf6b174b..b89083eb 100644 --- a/crates/node/src/types/mod.rs +++ b/crates/node/src/types/mod.rs @@ -75,9 +75,46 @@ pub(crate) use init::{ InitApiResponse, InitData, InitParams, VALID_CONFIG_FORMATS, VALID_STRATEGIES, }; -// TODO: will be implemented on story 7.1 (config types) +// Config types (Story 7.1 - Implemented) pub(crate) mod config; +// Re-export config types for easier access +// Allow unused imports - these will be used by config commands (Stories 7.2-7.3) +#[allow(unused_imports)] +pub(crate) use config::{ + // Configuration Structures + AuditConfigInfo, + AuditSectionsConfigInfo, + BackupConfigInfo, + ChangelogConfigInfo, + ChangesetConfigInfo, + ConfigData, + // API Responses + ConfigShowApiResponse, + // Response Data + ConfigShowData, + // Input Parameters + ConfigShowParams, + ConfigValidateApiResponse, + ConfigValidateData, + ConfigValidateParams, + ConfigValidationIssue, + DependencyConfigInfo, + ExecuteConfigInfo, + GitConfigInfo, + HealthScoreWeightsInfo, + RegistryConfigInfo, + ScopedRegistryEntry, + UpgradeConfigInfo, + VersionConfigInfo, + // Constants + VALID_BUMP_TYPES, + VALID_CHANGELOG_FORMATS, + VALID_MONOREPO_MODES, + VALID_SEVERITY_LEVELS, + VALID_STRATEGIES as CONFIG_VALID_STRATEGIES, +}; + // Changeset types (Story 4.1 - Implemented) pub(crate) mod changeset; @@ -139,13 +176,13 @@ pub(crate) use bump::{ BumpSnapshotData, BumpSnapshotParams, BumpSummaryInfo, - // Constants - COMMON_PRERELEASE_TAGS, - DEFAULT_SNAPSHOT_FORMAT, DependencyUpdateInfo, // Supporting Types PackageVersionInfo, SnapshotVersionInfo, + // Constants + COMMON_PRERELEASE_TAGS, + DEFAULT_SNAPSHOT_FORMAT, VALID_DEPENDENCY_TYPES, }; From c39100711297fd63c0c9b388825b0602894b5c77 Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:44:27 +0000 Subject: [PATCH 3/7] test(WOR-TSK-202): add comprehensive tests for config types Add 78 new tests across 7 test modules: - config_params_tests: ConfigShowParams and ConfigValidateParams - config_info_tests: all configuration section structures - config_data_tests: ConfigData and ConfigShowData - config_validation_tests: ConfigValidationIssue and ConfigValidateData - config_api_response_tests: API response wrappers - config_constants_tests: validation constants - config_scenario_tests: complete workflow scenarios Tests cover: - Construction and default values - Builder methods and factory functions - Clone and serialization - Error and success scenarios - Complete config show/validate workflows Total test count: 914 (78 new tests added) --- crates/node/src/tests.rs | 1039 +++++++++++++++++++++++++++++++++++++- 1 file changed, 1035 insertions(+), 4 deletions(-) diff --git a/crates/node/src/tests.rs b/crates/node/src/tests.rs index 8a0feb97..574e4819 100644 --- a/crates/node/src/tests.rs +++ b/crates/node/src/tests.rs @@ -31,7 +31,7 @@ /// Tests for lib.rs version functions and constants. #[cfg(test)] mod version_tests { - use crate::{VERSION, get_version}; + use crate::{get_version, VERSION}; #[test] #[allow(clippy::const_is_empty)] @@ -820,7 +820,7 @@ mod validation_tests { #[cfg(test)] mod response_tests { use crate::error::ErrorInfo; - use crate::response::{ApiResponse, ApiResponseExt, JsonResponse, result_to_response}; + use crate::response::{result_to_response, ApiResponse, ApiResponseExt, JsonResponse}; use serde::Serialize; use std::io::{Error as IoError, ErrorKind}; use sublime_cli_tools::error::CliError; @@ -3360,8 +3360,9 @@ mod bump_types_tests { use crate::types::bump::{ BumpApplyApiResponse, BumpApplyData, BumpApplyParams, BumpPreviewApiResponse, BumpPreviewData, BumpPreviewParams, BumpSnapshotApiResponse, BumpSnapshotData, - BumpSnapshotParams, BumpSummaryInfo, COMMON_PRERELEASE_TAGS, DEFAULT_SNAPSHOT_FORMAT, - DependencyUpdateInfo, PackageVersionInfo, SnapshotVersionInfo, VALID_DEPENDENCY_TYPES, + BumpSnapshotParams, BumpSummaryInfo, DependencyUpdateInfo, PackageVersionInfo, + SnapshotVersionInfo, COMMON_PRERELEASE_TAGS, DEFAULT_SNAPSHOT_FORMAT, + VALID_DEPENDENCY_TYPES, }; // ======================================================================== @@ -4686,3 +4687,1033 @@ mod execute_types_tests { assert!((data.summary.total_duration_ms - 50.0).abs() < f64::EPSILON); } } + +/// Tests for config types (Story 7.1). +/// Tests for ConfigShowParams, ConfigValidateParams, and related structures. +#[cfg(test)] +mod config_params_tests { + use crate::types::config::{ConfigShowParams, ConfigValidateParams}; + + #[test] + fn test_config_show_params_new() { + let params = ConfigShowParams::new(".".to_string()); + + assert_eq!(params.root, "."); + assert!(params.config_path.is_none()); + } + + #[test] + fn test_config_show_params_with_config() { + let params = + ConfigShowParams::with_config("/workspace".to_string(), "repo.config.json".to_string()); + + assert_eq!(params.root, "/workspace"); + assert_eq!(params.config_path, Some("repo.config.json".to_string())); + } + + #[test] + fn test_config_show_params_clone() { + let params = ConfigShowParams::with_config(".".to_string(), "custom.json".to_string()); + let cloned = params.clone(); + + assert_eq!(cloned.root, params.root); + assert_eq!(cloned.config_path, params.config_path); + } + + #[test] + fn test_config_show_params_debug() { + let params = ConfigShowParams::new(".".to_string()); + let debug_str = format!("{params:?}"); + + assert!(debug_str.contains("ConfigShowParams")); + assert!(debug_str.contains("root")); + } + + #[test] + fn test_config_show_params_serialize() { + let params = ConfigShowParams::new("/path/to/workspace".to_string()); + let json = serde_json::to_string(¶ms).unwrap(); + + assert!(json.contains("root")); + assert!(json.contains("/path/to/workspace")); + } + + #[test] + fn test_config_validate_params_new() { + let params = ConfigValidateParams::new(".".to_string()); + + assert_eq!(params.root, "."); + assert!(params.config_path.is_none()); + } + + #[test] + fn test_config_validate_params_with_config() { + let params = ConfigValidateParams::with_config( + "/workspace".to_string(), + "repo.config.toml".to_string(), + ); + + assert_eq!(params.root, "/workspace"); + assert_eq!(params.config_path, Some("repo.config.toml".to_string())); + } + + #[test] + fn test_config_validate_params_clone() { + let params = ConfigValidateParams::new("/project".to_string()); + let cloned = params.clone(); + + assert_eq!(cloned.root, params.root); + } +} + +/// Tests for config info structures (Story 7.1). +#[cfg(test)] +mod config_info_tests { + use crate::types::config::{ + AuditConfigInfo, AuditSectionsConfigInfo, BackupConfigInfo, ChangelogConfigInfo, + ChangesetConfigInfo, DependencyConfigInfo, ExecuteConfigInfo, GitConfigInfo, + HealthScoreWeightsInfo, RegistryConfigInfo, ScopedRegistryEntry, UpgradeConfigInfo, + VersionConfigInfo, + }; + + #[test] + fn test_changeset_config_info_new() { + let config = ChangesetConfigInfo::new( + ".changesets".to_string(), + ".changesets/history".to_string(), + vec!["production".to_string(), "staging".to_string()], + vec!["production".to_string()], + ); + + assert_eq!(config.path, ".changesets"); + assert_eq!(config.history_path, ".changesets/history"); + assert_eq!(config.available_environments.len(), 2); + assert_eq!(config.default_environments.len(), 1); + } + + #[test] + fn test_changeset_config_info_default() { + let config = ChangesetConfigInfo::default(); + + assert_eq!(config.path, ".changesets"); + assert_eq!(config.history_path, ".changesets/history"); + assert!(config.available_environments.is_empty()); + assert!(config.default_environments.is_empty()); + } + + #[test] + fn test_version_config_info_new() { + let config = VersionConfigInfo::new( + "independent".to_string(), + "minor".to_string(), + "{version}-snapshot".to_string(), + ); + + assert_eq!(config.strategy, "independent"); + assert_eq!(config.default_bump, "minor"); + assert_eq!(config.snapshot_format, "{version}-snapshot"); + } + + #[test] + fn test_version_config_info_default() { + let config = VersionConfigInfo::default(); + + assert_eq!(config.strategy, "independent"); + assert_eq!(config.default_bump, "patch"); + assert!(config.snapshot_format.contains("{version}")); + } + + #[test] + fn test_dependency_config_info_new() { + let config = DependencyConfigInfo::new( + "patch".to_string(), + true, + false, + false, + 10, + false, + true, + true, + true, + true, + ); + + assert_eq!(config.propagation_bump, "patch"); + assert!(config.propagate_dependencies); + assert!(!config.propagate_dev_dependencies); + assert_eq!(config.max_depth, 10); + assert!(config.skip_workspace_protocol); + } + + #[test] + fn test_dependency_config_info_default() { + let config = DependencyConfigInfo::default(); + + assert_eq!(config.propagation_bump, "patch"); + assert!(config.propagate_dependencies); + assert!(!config.propagate_dev_dependencies); + assert!(!config.propagate_peer_dependencies); + assert_eq!(config.max_depth, 10); + assert!(!config.fail_on_circular); + } + + #[test] + fn test_registry_config_info_new() { + let scoped = vec![ScopedRegistryEntry::new( + "@myorg".to_string(), + "https://npm.myorg.com".to_string(), + )]; + let config = + RegistryConfigInfo::new("https://registry.npmjs.org".to_string(), scoped, 30, 3, true); + + assert_eq!(config.default_registry, "https://registry.npmjs.org"); + assert_eq!(config.scoped_registries.len(), 1); + assert_eq!(config.timeout_secs, 30); + assert_eq!(config.retry_attempts, 3); + assert!(config.read_npmrc); + } + + #[test] + fn test_registry_config_info_default() { + let config = RegistryConfigInfo::default(); + + assert_eq!(config.default_registry, "https://registry.npmjs.org"); + assert!(config.scoped_registries.is_empty()); + assert_eq!(config.timeout_secs, 30); + assert_eq!(config.retry_attempts, 3); + assert!(config.read_npmrc); + } + + #[test] + fn test_scoped_registry_entry_new() { + let entry = ScopedRegistryEntry::new( + "@websublime".to_string(), + "https://npm.websublime.dev".to_string(), + ); + + assert_eq!(entry.scope, "@websublime"); + assert_eq!(entry.registry, "https://npm.websublime.dev"); + } + + #[test] + fn test_backup_config_info_new() { + let config = BackupConfigInfo::new(true, ".backups".to_string(), 5); + + assert!(config.enabled); + assert_eq!(config.path, ".backups"); + assert_eq!(config.keep_count, 5); + } + + #[test] + fn test_backup_config_info_default() { + let config = BackupConfigInfo::default(); + + assert!(config.enabled); + assert_eq!(config.path, ".backups"); + assert_eq!(config.keep_count, 5); + } + + #[test] + fn test_upgrade_config_info_new() { + let registry = RegistryConfigInfo::default(); + let backup = BackupConfigInfo::default(); + let config = + UpgradeConfigInfo::new(true, "patch".to_string(), registry.clone(), backup.clone()); + + assert!(config.auto_changeset); + assert_eq!(config.changeset_bump, "patch"); + assert_eq!(config.registry.default_registry, registry.default_registry); + } + + #[test] + fn test_upgrade_config_info_default() { + let config = UpgradeConfigInfo::default(); + + assert!(config.auto_changeset); + assert_eq!(config.changeset_bump, "patch"); + assert_eq!(config.registry.timeout_secs, 30); + assert!(config.backup.enabled); + } + + #[test] + fn test_changelog_config_info_new() { + let config = ChangelogConfigInfo::new( + true, + "keep-a-changelog".to_string(), + true, + Some("https://github.com/org/repo".to_string()), + true, + None, + vec![], + "per-package".to_string(), + ); + + assert!(config.enabled); + assert_eq!(config.format, "keep-a-changelog"); + assert!(config.include_commit_links); + assert!(config.repository_url.is_some()); + assert!(config.conventional); + assert!(config.template.is_none()); + } + + #[test] + fn test_changelog_config_info_default() { + let config = ChangelogConfigInfo::default(); + + assert!(config.enabled); + assert_eq!(config.format, "keep-a-changelog"); + assert!(config.include_commit_links); + assert!(config.conventional); + assert_eq!(config.monorepo_mode, "per-package"); + } + + #[test] + fn test_audit_sections_config_info_new() { + let config = AuditSectionsConfigInfo::new(true, true, false, false); + + assert!(config.upgrades); + assert!(config.dependencies); + assert!(!config.version_consistency); + assert!(!config.breaking_changes); + } + + #[test] + fn test_audit_sections_config_info_default() { + let config = AuditSectionsConfigInfo::default(); + + assert!(config.upgrades); + assert!(config.dependencies); + assert!(config.version_consistency); + assert!(config.breaking_changes); + } + + #[test] + fn test_health_score_weights_info_new() { + let config = HealthScoreWeightsInfo::new(0.4, 0.3, 0.2, 0.1); + + assert!((config.upgrades_weight - 0.4).abs() < f64::EPSILON); + assert!((config.dependencies_weight - 0.3).abs() < f64::EPSILON); + assert!((config.version_consistency_weight - 0.2).abs() < f64::EPSILON); + assert!((config.breaking_changes_weight - 0.1).abs() < f64::EPSILON); + } + + #[test] + fn test_health_score_weights_info_default() { + let config = HealthScoreWeightsInfo::default(); + + // All weights should be 0.25 by default + assert!((config.upgrades_weight - 0.25).abs() < f64::EPSILON); + assert!((config.dependencies_weight - 0.25).abs() < f64::EPSILON); + assert!((config.version_consistency_weight - 0.25).abs() < f64::EPSILON); + assert!((config.breaking_changes_weight - 0.25).abs() < f64::EPSILON); + } + + #[test] + fn test_audit_config_info_new() { + let sections = AuditSectionsConfigInfo::default(); + let weights = HealthScoreWeightsInfo::default(); + let config = AuditConfigInfo::new(true, "medium".to_string(), sections, weights); + + assert!(config.enabled); + assert_eq!(config.min_severity, "medium"); + } + + #[test] + fn test_audit_config_info_default() { + let config = AuditConfigInfo::default(); + + assert!(config.enabled); + assert_eq!(config.min_severity, "low"); + assert!(config.sections.upgrades); + } + + #[test] + fn test_git_config_info_new() { + let config = GitConfigInfo::new("develop".to_string(), true); + + assert_eq!(config.branch_base, "develop"); + assert!(config.detect_affected_packages); + } + + #[test] + fn test_git_config_info_default() { + let config = GitConfigInfo::default(); + + assert_eq!(config.branch_base, "main"); + assert!(config.detect_affected_packages); + } + + #[test] + fn test_execute_config_info_new() { + let config = ExecuteConfigInfo::new(600, 120, 8); + + assert_eq!(config.timeout_secs, 600); + assert_eq!(config.per_package_timeout_secs, 120); + assert_eq!(config.max_parallel, 8); + } + + #[test] + fn test_execute_config_info_default() { + let config = ExecuteConfigInfo::default(); + + assert_eq!(config.timeout_secs, 300); + assert_eq!(config.per_package_timeout_secs, 60); + assert_eq!(config.max_parallel, 4); + } +} + +/// Tests for ConfigData and ConfigShowData (Story 7.1). +#[cfg(test)] +mod config_data_tests { + use crate::types::config::{ + AuditConfigInfo, ChangelogConfigInfo, ChangesetConfigInfo, ConfigData, ConfigShowData, + DependencyConfigInfo, ExecuteConfigInfo, GitConfigInfo, UpgradeConfigInfo, + VersionConfigInfo, + }; + + #[test] + fn test_config_data_new() { + let config = ConfigData::new( + ChangesetConfigInfo::default(), + VersionConfigInfo::default(), + DependencyConfigInfo::default(), + UpgradeConfigInfo::default(), + ChangelogConfigInfo::default(), + AuditConfigInfo::default(), + GitConfigInfo::default(), + ExecuteConfigInfo::default(), + ); + + assert_eq!(config.changeset.path, ".changesets"); + assert_eq!(config.version.strategy, "independent"); + assert!(config.dependency.propagate_dependencies); + } + + #[test] + fn test_config_data_default() { + let config = ConfigData::default(); + + assert_eq!(config.changeset.path, ".changesets"); + assert_eq!(config.version.strategy, "independent"); + assert_eq!(config.version.default_bump, "patch"); + assert!(config.dependency.propagate_dependencies); + assert!(config.upgrade.auto_changeset); + assert!(config.changelog.enabled); + assert!(config.audit.enabled); + assert_eq!(config.git.branch_base, "main"); + assert_eq!(config.execute.max_parallel, 4); + } + + #[test] + fn test_config_data_clone() { + let config = ConfigData::default(); + let cloned = config.clone(); + + assert_eq!(cloned.changeset.path, config.changeset.path); + assert_eq!(cloned.version.strategy, config.version.strategy); + } + + #[test] + fn test_config_data_serialize() { + let config = ConfigData::default(); + let json = serde_json::to_string(&config).unwrap(); + + assert!(json.contains("changeset")); + assert!(json.contains("version")); + assert!(json.contains("dependency")); + assert!(json.contains("upgrade")); + assert!(json.contains("changelog")); + assert!(json.contains("audit")); + assert!(json.contains("git")); + assert!(json.contains("execute")); + } + + #[test] + fn test_config_show_data_new() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.json".to_string(), "json".to_string(), config); + + assert_eq!(show_data.config_path, "repo.config.json"); + assert_eq!(show_data.config_format, "json"); + assert_eq!(show_data.config.version.strategy, "independent"); + } + + #[test] + fn test_config_show_data_with_toml_format() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.toml".to_string(), "toml".to_string(), config); + + assert_eq!(show_data.config_format, "toml"); + } + + #[test] + fn test_config_show_data_with_yaml_format() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.yaml".to_string(), "yaml".to_string(), config); + + assert_eq!(show_data.config_format, "yaml"); + } + + #[test] + fn test_config_show_data_clone() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.json".to_string(), "json".to_string(), config); + let cloned = show_data.clone(); + + assert_eq!(cloned.config_path, show_data.config_path); + assert_eq!(cloned.config_format, show_data.config_format); + } + + #[test] + fn test_config_show_data_serialize() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.json".to_string(), "json".to_string(), config); + let json = serde_json::to_string(&show_data).unwrap(); + + assert!(json.contains("config_path")); + assert!(json.contains("config_format")); + assert!(json.contains("repo.config.json")); + } +} + +/// Tests for ConfigValidationIssue and ConfigValidateData (Story 7.1). +#[cfg(test)] +mod config_validation_tests { + use crate::types::config::{ConfigValidateData, ConfigValidationIssue}; + + #[test] + fn test_config_validation_issue_error() { + let issue = ConfigValidationIssue::error( + "version.strategy".to_string(), + "Invalid strategy value".to_string(), + ); + + assert_eq!(issue.severity, "error"); + assert_eq!(issue.field, "version.strategy"); + assert_eq!(issue.message, "Invalid strategy value"); + assert!(issue.suggestion.is_none()); + } + + #[test] + fn test_config_validation_issue_error_with_suggestion() { + let issue = ConfigValidationIssue::error_with_suggestion( + "version.strategy".to_string(), + "Invalid strategy value".to_string(), + "Use 'independent' or 'unified'".to_string(), + ); + + assert_eq!(issue.severity, "error"); + assert!(issue.is_error()); + assert!(!issue.is_warning()); + assert!(issue.suggestion.is_some()); + assert_eq!(issue.suggestion.unwrap(), "Use 'independent' or 'unified'"); + } + + #[test] + fn test_config_validation_issue_warning() { + let issue = ConfigValidationIssue::warning( + "changelog.repositoryUrl".to_string(), + "Repository URL not set".to_string(), + ); + + assert_eq!(issue.severity, "warning"); + assert!(issue.is_warning()); + assert!(!issue.is_error()); + assert!(!issue.is_info()); + } + + #[test] + fn test_config_validation_issue_warning_with_suggestion() { + let issue = ConfigValidationIssue::warning_with_suggestion( + "changelog.repositoryUrl".to_string(), + "Repository URL not set".to_string(), + "Add repository URL for commit links".to_string(), + ); + + assert!(issue.is_warning()); + assert!(issue.suggestion.is_some()); + } + + #[test] + fn test_config_validation_issue_info() { + let issue = ConfigValidationIssue::info( + "execute.maxParallel".to_string(), + "Consider increasing for faster builds".to_string(), + ); + + assert_eq!(issue.severity, "info"); + assert!(issue.is_info()); + assert!(!issue.is_error()); + assert!(!issue.is_warning()); + } + + #[test] + fn test_config_validation_issue_new() { + let issue = ConfigValidationIssue::new( + "warning".to_string(), + "test.field".to_string(), + "Test message".to_string(), + Some("Fix suggestion".to_string()), + ); + + assert_eq!(issue.severity, "warning"); + assert_eq!(issue.field, "test.field"); + assert_eq!(issue.message, "Test message"); + assert_eq!(issue.suggestion, Some("Fix suggestion".to_string())); + } + + #[test] + fn test_config_validation_issue_clone() { + let issue = ConfigValidationIssue::error("field".to_string(), "message".to_string()); + let cloned = issue.clone(); + + assert_eq!(cloned.severity, issue.severity); + assert_eq!(cloned.field, issue.field); + } + + #[test] + fn test_config_validate_data_new() { + let errors = vec![ConfigValidationIssue::error( + "version.strategy".to_string(), + "Invalid".to_string(), + )]; + let warnings = vec![ConfigValidationIssue::warning( + "changelog.repositoryUrl".to_string(), + "Missing".to_string(), + )]; + + let data = ConfigValidateData::new(false, "repo.config.json".to_string(), errors, warnings); + + assert!(!data.valid); + assert_eq!(data.config_path, "repo.config.json"); + assert_eq!(data.errors.len(), 1); + assert_eq!(data.warnings.len(), 1); + } + + #[test] + fn test_config_validate_data_valid() { + let data = ConfigValidateData::valid("repo.config.json".to_string()); + + assert!(data.valid); + assert!(data.errors.is_empty()); + assert!(data.warnings.is_empty()); + assert!(!data.has_errors()); + assert!(!data.has_warnings()); + assert_eq!(data.total_issues(), 0); + } + + #[test] + fn test_config_validate_data_valid_with_warnings() { + let warnings = + vec![ConfigValidationIssue::warning("field".to_string(), "warning".to_string())]; + let data = + ConfigValidateData::valid_with_warnings("repo.config.json".to_string(), warnings); + + assert!(data.valid); + assert!(data.errors.is_empty()); + assert!(!data.warnings.is_empty()); + assert!(!data.has_errors()); + assert!(data.has_warnings()); + assert_eq!(data.total_issues(), 1); + } + + #[test] + fn test_config_validate_data_invalid() { + let errors = vec![ + ConfigValidationIssue::error("field1".to_string(), "error1".to_string()), + ConfigValidationIssue::error("field2".to_string(), "error2".to_string()), + ]; + let data = ConfigValidateData::invalid("repo.config.json".to_string(), errors); + + assert!(!data.valid); + assert_eq!(data.errors.len(), 2); + assert!(data.warnings.is_empty()); + assert!(data.has_errors()); + assert!(!data.has_warnings()); + assert_eq!(data.total_issues(), 2); + } + + #[test] + fn test_config_validate_data_invalid_with_warnings() { + let errors = vec![ConfigValidationIssue::error("field".to_string(), "error".to_string())]; + let warnings = + vec![ConfigValidationIssue::warning("field".to_string(), "warning".to_string())]; + let data = ConfigValidateData::invalid_with_warnings( + "repo.config.json".to_string(), + errors, + warnings, + ); + + assert!(!data.valid); + assert!(data.has_errors()); + assert!(data.has_warnings()); + assert_eq!(data.total_issues(), 2); + } + + #[test] + fn test_config_validate_data_serialize() { + let data = ConfigValidateData::valid("repo.config.json".to_string()); + let json = serde_json::to_string(&data).unwrap(); + + assert!(json.contains("valid")); + assert!(json.contains("config_path")); + assert!(json.contains("errors")); + assert!(json.contains("warnings")); + } +} + +/// Tests for ConfigShowApiResponse and ConfigValidateApiResponse (Story 7.1). +#[cfg(test)] +mod config_api_response_tests { + use crate::error::ErrorInfo; + use crate::types::config::{ + ConfigData, ConfigShowApiResponse, ConfigShowData, ConfigValidateApiResponse, + ConfigValidateData, + }; + + #[test] + fn test_config_show_api_response_success() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.json".to_string(), "json".to_string(), config); + let response = ConfigShowApiResponse::success(show_data); + + assert!(response.success); + assert!(response.is_success()); + assert!(!response.is_failure()); + assert!(response.data.is_some()); + assert!(response.error.is_none()); + } + + #[test] + fn test_config_show_api_response_failure() { + let error = ErrorInfo::not_found("Config file not found", Some("repo.config.json")); + let response = ConfigShowApiResponse::failure(error); + + assert!(!response.success); + assert!(!response.is_success()); + assert!(response.is_failure()); + assert!(response.data.is_none()); + assert!(response.error.is_some()); + assert_eq!(response.error.as_ref().unwrap().code, "ENOENT"); + } + + #[test] + fn test_config_show_api_response_failure_with_different_error_codes() { + // Test ECONFIG + let error = ErrorInfo::configuration("Invalid configuration format"); + let response = ConfigShowApiResponse::failure(error); + assert_eq!(response.error.as_ref().unwrap().code, "ECONFIG"); + + // Test EVALIDATION + let error = ErrorInfo::validation("Invalid root path", Some("root")); + let response = ConfigShowApiResponse::failure(error); + assert_eq!(response.error.as_ref().unwrap().code, "EVALIDATION"); + } + + #[test] + fn test_config_show_api_response_clone() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.json".to_string(), "json".to_string(), config); + let response = ConfigShowApiResponse::success(show_data); + let cloned = response.clone(); + + assert_eq!(cloned.success, response.success); + } + + #[test] + fn test_config_show_api_response_serialize_success() { + let config = ConfigData::default(); + let show_data = + ConfigShowData::new("repo.config.json".to_string(), "json".to_string(), config); + let response = ConfigShowApiResponse::success(show_data); + let json = serde_json::to_string(&response).unwrap(); + + assert!(json.contains("\"success\":true")); + assert!(json.contains("data")); + } + + #[test] + fn test_config_show_api_response_serialize_failure() { + let error = ErrorInfo::not_found("Not found", None::); + let response = ConfigShowApiResponse::failure(error); + let json = serde_json::to_string(&response).unwrap(); + + assert!(json.contains("\"success\":false")); + assert!(json.contains("error")); + } + + #[test] + fn test_config_validate_api_response_success() { + let data = ConfigValidateData::valid("repo.config.json".to_string()); + let response = ConfigValidateApiResponse::success(data); + + assert!(response.success); + assert!(response.is_success()); + assert!(!response.is_failure()); + assert!(response.data.is_some()); + assert!(response.data.as_ref().unwrap().valid); + } + + #[test] + fn test_config_validate_api_response_success_with_validation_errors() { + // The API response is still "success" because the command executed + // The validation data shows whether the config is valid + let data = ConfigValidateData::invalid( + "repo.config.json".to_string(), + vec![crate::types::config::ConfigValidationIssue::error( + "field".to_string(), + "error".to_string(), + )], + ); + let response = ConfigValidateApiResponse::success(data); + + assert!(response.success); // API call succeeded + assert!(!response.data.as_ref().unwrap().valid); // But config is invalid + } + + #[test] + fn test_config_validate_api_response_failure() { + let error = ErrorInfo::not_found("Config file not found", Some("repo.config.json")); + let response = ConfigValidateApiResponse::failure(error); + + assert!(!response.success); + assert!(response.is_failure()); + assert!(response.data.is_none()); + assert!(response.error.is_some()); + } + + #[test] + fn test_config_validate_api_response_clone() { + let data = ConfigValidateData::valid("repo.config.json".to_string()); + let response = ConfigValidateApiResponse::success(data); + let cloned = response.clone(); + + assert_eq!(cloned.success, response.success); + } + + #[test] + fn test_config_validate_api_response_serialize_success() { + let data = ConfigValidateData::valid("repo.config.json".to_string()); + let response = ConfigValidateApiResponse::success(data); + let json = serde_json::to_string(&response).unwrap(); + + assert!(json.contains("\"success\":true")); + assert!(json.contains("\"valid\":true")); + } + + #[test] + fn test_config_validate_api_response_serialize_failure() { + let error = ErrorInfo::configuration("Parse error"); + let response = ConfigValidateApiResponse::failure(error); + let json = serde_json::to_string(&response).unwrap(); + + assert!(json.contains("\"success\":false")); + assert!(json.contains("ECONFIG")); + } +} + +/// Tests for config constants (Story 7.1). +#[cfg(test)] +mod config_constants_tests { + use crate::types::config::{ + VALID_BUMP_TYPES, VALID_CHANGELOG_FORMATS, VALID_MONOREPO_MODES, VALID_SEVERITY_LEVELS, + VALID_STRATEGIES, + }; + + #[test] + fn test_valid_strategies() { + assert_eq!(VALID_STRATEGIES.len(), 2); + assert!(VALID_STRATEGIES.contains(&"independent")); + assert!(VALID_STRATEGIES.contains(&"unified")); + } + + #[test] + fn test_valid_bump_types() { + assert_eq!(VALID_BUMP_TYPES.len(), 4); + assert!(VALID_BUMP_TYPES.contains(&"major")); + assert!(VALID_BUMP_TYPES.contains(&"minor")); + assert!(VALID_BUMP_TYPES.contains(&"patch")); + assert!(VALID_BUMP_TYPES.contains(&"none")); + } + + #[test] + fn test_valid_changelog_formats() { + assert_eq!(VALID_CHANGELOG_FORMATS.len(), 3); + assert!(VALID_CHANGELOG_FORMATS.contains(&"keep-a-changelog")); + assert!(VALID_CHANGELOG_FORMATS.contains(&"conventional-commits")); + assert!(VALID_CHANGELOG_FORMATS.contains(&"custom")); + } + + #[test] + fn test_valid_monorepo_modes() { + assert_eq!(VALID_MONOREPO_MODES.len(), 3); + assert!(VALID_MONOREPO_MODES.contains(&"per-package")); + assert!(VALID_MONOREPO_MODES.contains(&"root")); + assert!(VALID_MONOREPO_MODES.contains(&"both")); + } + + #[test] + fn test_valid_severity_levels() { + assert_eq!(VALID_SEVERITY_LEVELS.len(), 3); + assert!(VALID_SEVERITY_LEVELS.contains(&"error")); + assert!(VALID_SEVERITY_LEVELS.contains(&"warning")); + assert!(VALID_SEVERITY_LEVELS.contains(&"info")); + } +} + +/// Complete scenario tests for config commands (Story 7.1). +#[cfg(test)] +mod config_scenario_tests { + use crate::error::ErrorInfo; + use crate::types::config::{ + ConfigData, ConfigShowApiResponse, ConfigShowData, ConfigShowParams, + ConfigValidateApiResponse, ConfigValidateData, ConfigValidateParams, ConfigValidationIssue, + VersionConfigInfo, + }; + + #[test] + fn test_complete_config_show_scenario() { + // Simulate a complete configShow workflow + let params = ConfigShowParams::new("/path/to/workspace".to_string()); + assert_eq!(params.root, "/path/to/workspace"); + + // Simulate loaded config with custom version strategy + let mut config = ConfigData::default(); + config.version = VersionConfigInfo::new( + "unified".to_string(), + "minor".to_string(), + "{version}-dev".to_string(), + ); + + let show_data = ConfigShowData::new( + "/path/to/workspace/repo.config.json".to_string(), + "json".to_string(), + config, + ); + + let response = ConfigShowApiResponse::success(show_data); + + assert!(response.is_success()); + let data = response.data.unwrap(); + assert_eq!(data.config_format, "json"); + assert_eq!(data.config.version.strategy, "unified"); + assert_eq!(data.config.version.default_bump, "minor"); + } + + #[test] + fn test_complete_config_validate_scenario_valid() { + // Simulate a complete configValidate workflow for valid config + let params = ConfigValidateParams::new(".".to_string()); + assert_eq!(params.root, "."); + + let data = ConfigValidateData::valid("repo.config.json".to_string()); + let response = ConfigValidateApiResponse::success(data); + + assert!(response.is_success()); + let data = response.data.unwrap(); + assert!(data.valid); + assert!(data.errors.is_empty()); + } + + #[test] + fn test_complete_config_validate_scenario_with_warnings() { + // Simulate validation with warnings but no errors + let warnings = vec![ + ConfigValidationIssue::warning( + "changelog.repositoryUrl".to_string(), + "Repository URL not set, commit links will not work".to_string(), + ), + ConfigValidationIssue::warning_with_suggestion( + "execute.maxParallel".to_string(), + "Low parallelism may slow down builds".to_string(), + "Consider increasing to match CPU cores".to_string(), + ), + ]; + + let data = + ConfigValidateData::valid_with_warnings("repo.config.json".to_string(), warnings); + + assert!(data.valid); + assert!(!data.has_errors()); + assert!(data.has_warnings()); + assert_eq!(data.warnings.len(), 2); + assert!(data.warnings[1].suggestion.is_some()); + } + + #[test] + fn test_complete_config_validate_scenario_invalid() { + // Simulate validation with errors + let errors = vec![ + ConfigValidationIssue::error( + "version.strategy".to_string(), + "Invalid strategy 'wrong'".to_string(), + ), + ConfigValidationIssue::error_with_suggestion( + "changeset.path".to_string(), + "Path does not exist".to_string(), + "Create the directory or update the path".to_string(), + ), + ]; + let warnings = vec![ConfigValidationIssue::warning( + "git.branchBase".to_string(), + "Branch 'master' is deprecated, consider using 'main'".to_string(), + )]; + + let data = ConfigValidateData::invalid_with_warnings( + "repo.config.json".to_string(), + errors, + warnings, + ); + + assert!(!data.valid); + assert!(data.has_errors()); + assert!(data.has_warnings()); + assert_eq!(data.total_issues(), 3); + + // Verify error details + assert!(data.errors[0].is_error()); + assert_eq!(data.errors[0].field, "version.strategy"); + assert!(data.errors[1].suggestion.is_some()); + } + + #[test] + fn test_config_show_error_scenario() { + // Simulate configShow failing because config file not found + let params = ConfigShowParams::new("/invalid/path".to_string()); + assert_eq!(params.root, "/invalid/path"); + + let error = ErrorInfo::not_found( + "Configuration file not found in /invalid/path", + Some("repo.config.json"), + ); + let response = ConfigShowApiResponse::failure(error); + + assert!(response.is_failure()); + let error = response.error.unwrap(); + assert_eq!(error.code, "ENOENT"); + assert!(error.message.contains("not found")); + } + + #[test] + fn test_config_validate_error_scenario() { + // Simulate configValidate failing because of parse error + let params = + ConfigValidateParams::with_config(".".to_string(), "broken.config.json".to_string()); + assert!(params.config_path.is_some()); + + let error = + ErrorInfo::configuration("Failed to parse configuration: unexpected token at line 5"); + let response = ConfigValidateApiResponse::failure(error); + + assert!(response.is_failure()); + let error = response.error.unwrap(); + assert_eq!(error.code, "ECONFIG"); + } +} From 5623fac3b629806c706e12b1f346e84369320847 Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:44:35 +0000 Subject: [PATCH 4/7] build(WOR-TSK-202): regenerate NAPI bindings with config types Regenerate binding.d.ts and binding.js with new config types. TypeScript definitions now include: - ConfigShowParams, ConfigValidateParams - ConfigShowData, ConfigValidateData - ConfigShowApiResponse, ConfigValidateApiResponse - ConfigValidationIssue, ConfigData - All configuration section interfaces Fixed documentation to use line comments instead of JSDoc in TypeScript examples to prevent parsing errors. --- packages/workspace-tools/src/binding.d.ts | 1470 +++++++++++++++++++-- packages/workspace-tools/src/binding.js | 104 +- 2 files changed, 1435 insertions(+), 139 deletions(-) diff --git a/packages/workspace-tools/src/binding.d.ts b/packages/workspace-tools/src/binding.d.ts index 98dd9ffb..7757d8e0 100644 --- a/packages/workspace-tools/src/binding.d.ts +++ b/packages/workspace-tools/src/binding.d.ts @@ -21,6 +21,160 @@ export interface ArchivedChangesetInfo { releaseInfo: ReleaseInfoData } +/** + * Audit configuration information. + * + * Contains settings for audit and health check functionality. + * + * # Fields + * + * - `enabled`: Whether audit is enabled + * - `min_severity`: Minimum severity level to report + * - `sections`: Which audit sections to run + * - `health_score_weights`: Weights for health score calculation + * + * # TypeScript Definition + * + * ```typescript + * interface AuditConfigInfo { + * // Whether audit is enabled + * enabled: boolean; + * // Minimum severity level to report: "critical", "high", "medium", "low", "info" + * minSeverity: string; + * // Which audit sections to run + * sections: AuditSectionsConfigInfo; + * // Weights for health score calculation + * healthScoreWeights: HealthScoreWeightsInfo; + * } + * ``` + */ +export interface AuditConfigInfo { + /** + * Whether audit is enabled. + * + * If `false`, audit commands are skipped. + */ + enabled: boolean + /** + * Minimum severity level to report. + * + * Only issues at or above this severity are reported: + * - `"critical"`: Only critical issues + * - `"high"`: High and above + * - `"medium"`: Medium and above + * - `"low"`: Low and above + * - `"info"`: All issues including informational + */ + minSeverity: string + /** + * Which audit sections to run. + * + * Allows selectively enabling or disabling specific audit checks. + */ + sections: AuditSectionsConfigInfo + /** + * Weights for health score calculation. + * + * Determines how different factors contribute to the overall + * health score. + */ + healthScoreWeights: HealthScoreWeightsInfo +} + +/** + * Audit sections configuration. + * + * Contains flags for enabling/disabling specific audit sections. + * + * # TypeScript Definition + * + * ```typescript + * interface AuditSectionsConfigInfo { + * // Check for available upgrades + * upgrades: boolean; + * // Analyze dependencies + * dependencies: boolean; + * // Check version consistency + * versionConsistency: boolean; + * // Detect breaking changes + * breakingChanges: boolean; + * } + * ``` + */ +export interface AuditSectionsConfigInfo { + /** + * Check for available upgrades. + * + * Analyzes dependencies for available updates. + */ + upgrades: boolean + /** + * Analyze dependencies. + * + * Checks for circular dependencies, missing dependencies, etc. + */ + dependencies: boolean + /** + * Check version consistency. + * + * Verifies that dependency versions are consistent across packages. + */ + versionConsistency: boolean + /** + * Detect breaking changes. + * + * Identifies potential breaking changes based on commits and changelogs. + */ + breakingChanges: boolean +} + +/** + * Backup configuration information. + * + * Contains settings for backup and rollback functionality. + * + * # Fields + * + * - `enabled`: Whether backup is enabled + * - `path`: Path to store backups + * - `keep_count`: Number of backups to keep + * + * # TypeScript Definition + * + * ```typescript + * interface BackupConfigInfo { + * // Whether backup is enabled + * enabled: boolean; + * // Path to store backups + * path: string; + * // Number of backups to keep + * keepCount: number; + * } + * ``` + */ +export interface BackupConfigInfo { + /** + * Whether backup is enabled. + * + * If `true`, backups are created before operations that modify + * package files, allowing rollback if needed. + */ + enabled: boolean + /** + * Path to store backups. + * + * The directory where backup files are stored. This should be + * outside the workspace to avoid being affected by operations. + */ + path: string + /** + * Number of backups to keep. + * + * Older backups beyond this count are automatically deleted. + */ + keepCount: number +} + /** * Git branch information. * @@ -1053,6 +1207,106 @@ export interface BumpSummaryInfo { patchBumps: number } +/** + * Changelog configuration information. + * + * Contains settings for changelog generation. + * + * # Fields + * + * - `enabled`: Whether changelog generation is enabled + * - `format`: Changelog format ("keep-a-changelog", "conventional-commits", "custom") + * - `include_commit_links`: Whether to include commit links + * - `repository_url`: Repository URL for generating links + * - `conventional`: Whether to use conventional commits parsing + * - `template`: Custom template path + * - `exclude`: Patterns to exclude from changelog + * - `monorepo_mode`: How to handle changelogs in monorepos + * + * # TypeScript Definition + * + * ```typescript + * interface ChangelogConfigInfo { + * // Whether changelog generation is enabled + * enabled: boolean; + * // Changelog format: "keep-a-changelog", "conventional-commits", or "custom" + * format: string; + * // Whether to include commit links + * includeCommitLinks: boolean; + * // Repository URL for generating links + * repositoryUrl?: string; + * // Whether to use conventional commits parsing + * conventional: boolean; + * // Custom template path + * template?: string; + * // Patterns to exclude from changelog + * exclude: string[]; + * // How to handle changelogs in monorepos: "per-package", "root", or "both" + * monorepoMode: string; + * } + * ``` + */ +export interface ChangelogConfigInfo { + /** + * Whether changelog generation is enabled. + * + * If `false`, no changelog files are generated or updated. + */ + enabled: boolean + /** + * Changelog format. + * + * The format to use for changelog entries: + * - `"keep-a-changelog"`: Keep a Changelog format + * - `"conventional-commits"`: Conventional Commits format + * - `"custom"`: Custom template-based format + */ + format: string + /** + * Whether to include commit links. + * + * If `true`, changelog entries include links to the relevant commits. + */ + includeCommitLinks: boolean + /** + * Repository URL for generating links. + * + * Used to generate links to commits, comparisons, and issues + * in the changelog. Example: "https://github.com/org/repo". + */ + repositoryUrl?: string | undefined + /** + * Whether to use conventional commits parsing. + * + * If `true`, commit messages are parsed using conventional commits + * specification to categorize changes. + */ + conventional: boolean + /** + * Custom template path. + * + * Path to a custom template file for changelog generation. + * Only used when `format` is `"custom"`. + */ + template?: string | undefined + /** + * Patterns to exclude from changelog. + * + * Commit messages or files matching these patterns are excluded + * from changelog generation. + */ + exclude: Array + /** + * How to handle changelogs in monorepos. + * + * Determines where changelog files are created: + * - `"per-package"`: Each package has its own CHANGELOG.md + * - `"root"`: Single CHANGELOG.md at the repository root + * - `"both"`: Both per-package and root changelogs + */ + monorepoMode: string +} + /** * Add a new changeset to the workspace. * @@ -1540,6 +1794,65 @@ export interface ChangesetCheckParams { branch?: string | undefined } +/** + * Changeset configuration information. + * + * Contains settings for changeset management, including paths and + * environment configuration. + * + * # Fields + * + * - `path`: Path to store active changesets + * - `history_path`: Path to store archived changesets + * - `available_environments`: List of valid environment names + * - `default_environments`: Default environments for new changesets + * + * # TypeScript Definition + * + * ```typescript + * interface ChangesetConfigInfo { + * // Path to store active changesets (default: ".changesets") + * path: string; + * // Path to store archived changesets + * historyPath: string; + * // List of valid environment names + * availableEnvironments: string[]; + * // Default environments for new changesets + * defaultEnvironments: string[]; + * } + * ``` + */ +export interface ChangesetConfigInfo { + /** + * Path to store active changesets. + * + * This is the directory where pending changeset files are stored. + * Default value is `.changesets`. + */ + path: string + /** + * Path to store archived changesets. + * + * This is the directory where consumed changeset files are moved + * after a version bump operation. Typically a subdirectory of `path`. + */ + historyPath: string + /** + * List of valid environment names. + * + * These are the environments that changesets can target. Common + * examples include "production", "staging", "development". + */ + availableEnvironments: Array + /** + * Default environments for new changesets. + * + * These environments are automatically assigned to new changesets + * if not explicitly specified. + */ + defaultEnvironments: Array +} + /** * Detailed changeset information. * @@ -2950,143 +3263,778 @@ export interface ChangesetUpdateParams { } /** - * Dependency update information for a package version bump. + * Main configuration data structure. * - * This structure captures information about how a dependency version - * was updated as part of the version bump process. Dependencies are - * updated when the package they depend on is bumped. + * Contains all configuration sections from the `repo.config` file. + * This is the root structure that holds all workspace tool settings. * * # Fields * - * - `name`: The dependency package name - * - `dependency_type`: The type of dependency (regular, dev, peer, optional) - * - `old_version`: The previous version specification - * - `new_version`: The new version specification + * - `changeset`: Changeset management configuration + * - `version`: Version resolution configuration + * - `dependency`: Dependency propagation configuration + * - `upgrade`: Upgrade detection and application configuration + * - `changelog`: Changelog generation configuration + * - `audit`: Audit and health check configuration + * - `git`: Git integration configuration + * - `execute`: Command execution configuration * * # TypeScript Definition * * ```typescript - * interface DependencyUpdateInfo { - * name: string; - * dependencyType: 'regular' | 'dev' | 'peer' | 'optional'; - * oldVersion: string; - * newVersion: string; + * interface ConfigData { + * // Changeset management configuration + * changeset: ChangesetConfigInfo; + * // Version resolution configuration + * version: VersionConfigInfo; + * // Dependency propagation configuration + * dependency: DependencyConfigInfo; + * // Upgrade detection and application configuration + * upgrade: UpgradeConfigInfo; + * // Changelog generation configuration + * changelog: ChangelogConfigInfo; + * // Audit and health check configuration + * audit: AuditConfigInfo; + * // Git integration configuration + * git: GitConfigInfo; + * // Command execution configuration + * execute: ExecuteConfigInfo; * } * ``` - * - * # Examples - * - * ```typescript - * const update: DependencyUpdateInfo = { - * name: '@scope/core', - * dependencyType: 'regular', - * oldVersion: '^1.0.0', - * newVersion: '^1.1.0' - * }; - * ``` */ -export interface DependencyUpdateInfo { +export interface ConfigData { /** - * The dependency package name. + * Changeset management configuration. * - * This is the name of the package that was updated as a dependency. - * May include scope (e.g., `@scope/package`). + * Settings for managing changesets including paths and environments. */ - name: string + changeset: ChangesetConfigInfo /** - * The type of dependency. + * Version resolution configuration. * - * One of: `regular`, `dev`, `peer`, `optional` + * Settings for version management including strategy and defaults. */ - dependencyType: string + version: VersionConfigInfo /** - * The previous version specification. + * Dependency propagation configuration. * - * This is the version range or exact version that was previously - * specified in package.json (e.g., `^1.0.0`, `~1.0.0`, `1.0.0`). + * Settings for how dependency updates propagate through the workspace. */ - oldVersion: string + dependency: DependencyConfigInfo /** - * The new version specification. + * Upgrade detection and application configuration. * - * This is the updated version range or exact version after the bump. + * Settings for checking and applying dependency upgrades. */ - newVersion: string + upgrade: UpgradeConfigInfo + /** + * Changelog generation configuration. + * + * Settings for generating and formatting changelog files. + */ + changelog: ChangelogConfigInfo + /** + * Audit and health check configuration. + * + * Settings for workspace health auditing. + */ + audit: AuditConfigInfo + /** + * Git integration configuration. + * + * Settings for Git-related operations. + */ + git: GitConfigInfo + /** + * Command execution configuration. + * + * Settings for running commands across packages. + */ + execute: ExecuteConfigInfo } /** - * Error information structure for Node.js bindings. + * API response wrapper for the `configShow` command. * - * This structure is exposed to JavaScript/TypeScript via napi-rs and provides - * detailed error information in a format familiar to Node.js developers. - * The `#[napi(object)]` attribute enables automatic conversion to JavaScript - * objects and TypeScript type generation. + * This structure wraps the `configShow` response with success/failure status + * and consistent error handling, following the pattern used across all + * NAPI commands. * * # Fields * - * - `code`: Node.js-style error code (e.g., "EVALIDATION", "EGIT") - * - `message`: Human-readable error message - * - `context`: Optional additional context (field name, path, etc.) - * - `kind`: Error category from the CLI layer + * - `success`: Whether the operation succeeded + * - `data`: The config show data (present when success is true) + * - `error`: Error information (present when success is false) * * # TypeScript Definition * * ```typescript - * export interface ErrorInfo { - * Node.js-style error code (e.g., "EVALIDATION", "EGIT") - * code: string; - * Human-readable error message - * message: string; - * Optional additional context about the error - * context?: string; - * Error category from CLI (for debugging) - * kind: string; + * interface ConfigShowApiResponse { + * // Whether the operation succeeded + * success: boolean; + * // The config show data (present when success is true) + * data?: ConfigShowData; + * // Error information (present when success is false) + * error?: ErrorInfo; * } * ``` * * # Examples * * ```typescript - * // In JavaScript/TypeScript: - * if (!result.success) { - * const { code, message, context, kind } = result.error; - * console.error(`[${code}] ${message}`); - * if (context) { - * console.error(`Context: ${context}`); - * } + * const result = await configShow({ root: '.' }); + * + * if (result.success) { + * // result.data is ConfigShowData + * console.log(result.data.config.version.strategy); + * } else { + * // result.error is ErrorInfo + * console.error(`[${result.error.code}] ${result.error.message}`); * } * ``` */ -export interface ErrorInfo { +export interface ConfigShowApiResponse { /** - * Node.js-style error code (e.g., "EVALIDATION", "EGIT"). - * - * These codes follow Node.js conventions and can be used for - * programmatic error handling in JavaScript/TypeScript. - * - * # Available Codes + * Whether the operation succeeded. * - * - `ECONFIG`: Configuration errors - * - `EVALIDATION`: Validation errors - * - `EEXEC`: Execution errors - * - `EGIT`: Git errors - * - `EPKG`: Package errors - * - `ENOENT`: File/path not found - * - `EIO`: I/O errors - * - `ENETWORK`: Network errors - * - `EUSER`: User errors - * - `ETIMEOUT`: Timeout errors + * - `true`: Operation completed successfully, `data` field will be present + * - `false`: Operation failed, `error` field will be present */ - code: string + success: boolean /** - * Human-readable error message. + * The config show data (only present when `success` is `true`). * - * This message is suitable for displaying to end users and - * provides a clear description of what went wrong. + * Contains the loaded configuration and its path. */ - message: string + data?: ConfigShowData | undefined /** - * Optional additional context for the error. + * Error information (only present when `success` is `false`). + * + * Contains structured error information with a Node.js-style error code, + * message, optional context, and error kind. + */ + error?: ErrorInfo | undefined +} + +/** + * Response data for the `configShow` command. + * + * Contains the loaded configuration and the path where it was found. + * + * # Fields + * + * - `config_path`: Path to the loaded configuration file + * - `config_format`: Format of the configuration file (json, toml, yaml) + * - `config`: The loaded configuration data + * + * # TypeScript Definition + * + * ```typescript + * interface ConfigShowData { + * // Path to the loaded configuration file + * configPath: string; + * // Format of the configuration file + * configFormat: string; + * // The loaded configuration data + * config: ConfigData; + * } + * ``` + * + * # Examples + * + * ```typescript + * const result = await configShow({ root: '.' }); + * if (result.success) { + * console.log(`Loaded from: ${result.data.configPath}`); + * console.log(`Format: ${result.data.configFormat}`); + * console.log(`Strategy: ${result.data.config.version.strategy}`); + * } + * ``` + */ +export interface ConfigShowData { + /** + * Path to the loaded configuration file. + * + * The absolute or relative path where the configuration was found. + * Examples: "repo.config.json", "/path/to/repo.config.toml". + */ + configPath: string + /** + * Format of the configuration file. + * + * The detected format based on file extension: + * - `"json"`: JSON format + * - `"toml"`: TOML format + * - `"yaml"`: YAML format + */ + configFormat: string + /** + * The loaded configuration data. + * + * Contains all configuration sections parsed from the file. + */ + config: ConfigData +} + +/** + * Input parameters for the `configShow` command. + * + * This structure defines the parameters that can be passed to the `configShow` + * function from JavaScript/TypeScript. The root path is required, while + * the config path is optional. + * + * # Fields + * + * - `root`: The workspace root directory path (required) + * - `config_path`: Optional path to a custom configuration file + * + * # TypeScript Definition + * + * ```typescript + * interface ConfigShowParams { + * // Workspace root directory path + * root: string; + * // Optional custom config file path + * configPath?: string; + * } + * ``` + * + * # Examples + * + * ```typescript + * // Minimal params with just root + * const params: ConfigShowParams = { root: '.' }; + * + * // With custom config path + * const paramsWithConfig: ConfigShowParams = { + * root: '/path/to/workspace', + * configPath: '/path/to/custom/repo.config.json' + * }; + * ``` + */ +export interface ConfigShowParams { + /** + * Workspace root directory path. + * + * This is the absolute or relative path to the root of the workspace. + * The configuration file will be searched for in this directory unless + * a custom `configPath` is provided. + */ + root: string + /** + * Optional custom configuration file path. + * + * If not provided, the command will search for configuration files + * in standard locations (`repo.config.json`, `repo.config.toml`, + * `repo.config.yaml`) within the workspace root. + */ + configPath?: string | undefined +} + +/** + * API response wrapper for the `configValidate` command. + * + * This structure wraps the `configValidate` response with success/failure status + * and consistent error handling, following the pattern used across all + * NAPI commands. + * + * # Fields + * + * - `success`: Whether the operation succeeded + * - `data`: The config validate data (present when success is true) + * - `error`: Error information (present when success is false) + * + * # TypeScript Definition + * + * ```typescript + * interface ConfigValidateApiResponse { + * // Whether the operation succeeded + * success: boolean; + * // The config validate data (present when success is true) + * data?: ConfigValidateData; + * // Error information (present when success is false) + * error?: ErrorInfo; + * } + * ``` + * + * # Examples + * + * ```typescript + * const result = await configValidate({ root: '.' }); + * + * if (result.success) { + * // result.data is ConfigValidateData + * console.log(`Valid: ${result.data.valid}`); + * console.log(`Errors: ${result.data.errors.length}`); + * } else { + * // result.error is ErrorInfo + * console.error(`[${result.error.code}] ${result.error.message}`); + * } + * ``` + */ +export interface ConfigValidateApiResponse { + /** + * Whether the operation succeeded. + * + * - `true`: Operation completed successfully, `data` field will be present + * - `false`: Operation failed, `error` field will be present + */ + success: boolean + /** + * The config validate data (only present when `success` is `true`). + * + * Contains validation results including whether the config is valid + * and any issues found. + */ + data?: ConfigValidateData | undefined + /** + * Error information (only present when `success` is `false`). + * + * Contains structured error information with a Node.js-style error code, + * message, optional context, and error kind. + */ + error?: ErrorInfo | undefined +} + +/** + * Response data for the `configValidate` command. + * + * Contains validation results including whether the configuration is valid + * and any issues found. + * + * # Fields + * + * - `valid`: Whether the configuration is valid (no errors) + * - `config_path`: Path to the validated configuration file + * - `errors`: List of validation errors + * - `warnings`: List of validation warnings + * + * # TypeScript Definition + * + * ```typescript + * interface ConfigValidateData { + * // Whether the configuration is valid (no errors) + * valid: boolean; + * // Path to the validated configuration file + * configPath: string; + * // List of validation errors + * errors: ConfigValidationIssue[]; + * // List of validation warnings + * warnings: ConfigValidationIssue[]; + * } + * ``` + * + * # Examples + * + * ```typescript + * const result = await configValidate({ root: '.' }); + * if (result.success) { + * if (result.data.valid) { + * console.log('Configuration is valid!'); + * } else { + * console.error(`Found ${result.data.errors.length} errors`); + * for (const error of result.data.errors) { + * console.error(` - [${error.field}]: ${error.message}`); + * } + * } + * } + * ``` + */ +export interface ConfigValidateData { + /** + * Whether the configuration is valid. + * + * `true` if no errors were found (warnings are allowed), + * `false` if there are any validation errors. + */ + valid: boolean + /** + * Path to the validated configuration file. + * + * The path where the configuration file was found and validated. + */ + configPath: string + /** + * List of validation errors. + * + * Critical issues that must be fixed for the configuration to be valid. + */ + errors: Array + /** + * List of validation warnings. + * + * Non-critical issues that should be addressed but don't prevent + * the configuration from being used. + */ + warnings: Array +} + +/** + * Input parameters for the `configValidate` command. + * + * This structure defines the parameters that can be passed to the `configValidate` + * function from JavaScript/TypeScript. The root path is required, while + * the config path is optional. + * + * # Fields + * + * - `root`: The workspace root directory path (required) + * - `config_path`: Optional path to a custom configuration file + * + * # TypeScript Definition + * + * ```typescript + * interface ConfigValidateParams { + * // Workspace root directory path + * root: string; + * // Optional custom config file path + * configPath?: string; + * } + * ``` + * + * # Examples + * + * ```typescript + * // Minimal params with just root + * const params: ConfigValidateParams = { root: '.' }; + * + * // With custom config path + * const paramsWithConfig: ConfigValidateParams = { + * root: '/path/to/workspace', + * configPath: '/path/to/custom/repo.config.json' + * }; + * ``` + */ +export interface ConfigValidateParams { + /** + * Workspace root directory path. + * + * This is the absolute or relative path to the root of the workspace. + * The configuration file will be searched for in this directory unless + * a custom `configPath` is provided. + */ + root: string + /** + * Optional custom configuration file path. + * + * If not provided, the command will search for configuration files + * in standard locations (`repo.config.json`, `repo.config.toml`, + * `repo.config.yaml`) within the workspace root. + */ + configPath?: string | undefined +} + +/** + * Validation issue information. + * + * Represents a single validation issue found during configuration validation. + * + * # Fields + * + * - `severity`: Issue severity ("error", "warning", or "info") + * - `field`: The configuration field with the issue + * - `message`: Human-readable description of the issue + * - `suggestion`: Optional suggestion for fixing the issue + * + * # TypeScript Definition + * + * ```typescript + * interface ConfigValidationIssue { + * // Issue severity: "error", "warning", or "info" + * severity: string; + * // The configuration field with the issue + * field: string; + * // Human-readable description of the issue + * message: string; + * // Optional suggestion for fixing the issue + * suggestion?: string; + * } + * ``` + */ +export interface ConfigValidationIssue { + /** + * Issue severity. + * + * Indicates the importance of the issue: + * - `"error"`: Critical issue that must be fixed + * - `"warning"`: Potential problem that should be addressed + * - `"info"`: Informational note for improvement + */ + severity: string + /** + * The configuration field with the issue. + * + * Dot-notation path to the field, e.g., "version.strategy" or + * "changeset.path". + */ + field: string + /** + * Human-readable description of the issue. + * + * Explains what is wrong with the configuration. + */ + message: string + /** + * Optional suggestion for fixing the issue. + * + * Provides guidance on how to resolve the issue. + */ + suggestion?: string | undefined +} + +/** + * Dependency configuration information. + * + * Contains settings for dependency propagation during version bumps. + * + * # Fields + * + * - `propagation_bump`: Version bump type for dependency updates + * - `propagate_dependencies`: Whether to propagate regular dependencies + * - `propagate_dev_dependencies`: Whether to propagate dev dependencies + * - `propagate_peer_dependencies`: Whether to propagate peer dependencies + * - `max_depth`: Maximum propagation depth + * - `fail_on_circular`: Whether to fail on circular dependencies + * - `skip_workspace_protocol`: Skip workspace: protocol dependencies + * - `skip_file_protocol`: Skip file: protocol dependencies + * - `skip_link_protocol`: Skip link: protocol dependencies + * - `skip_portal_protocol`: Skip portal: protocol dependencies + * + * # TypeScript Definition + * + * ```typescript + * interface DependencyConfigInfo { + * // Version bump type for dependency updates + * propagationBump: string; + * // Whether to propagate regular dependencies + * propagateDependencies: boolean; + * // Whether to propagate dev dependencies + * propagateDevDependencies: boolean; + * // Whether to propagate peer dependencies + * propagatePeerDependencies: boolean; + * // Maximum propagation depth + * maxDepth: number; + * // Whether to fail on circular dependencies + * failOnCircular: boolean; + * // Skip workspace: protocol dependencies + * skipWorkspaceProtocol: boolean; + * // Skip file: protocol dependencies + * skipFileProtocol: boolean; + * // Skip link: protocol dependencies + * skipLinkProtocol: boolean; + * // Skip portal: protocol dependencies + * skipPortalProtocol: boolean; + * } + * ``` + */ +export interface DependencyConfigInfo { + /** + * Version bump type for dependency updates. + * + * When a package is updated, this determines how dependent packages + * have their versions bumped. Values: "major", "minor", "patch", "none". + */ + propagationBump: string + /** + * Whether to propagate regular dependencies. + * + * If `true`, packages that depend on updated packages will also + * be considered for version updates. + */ + propagateDependencies: boolean + /** + * Whether to propagate dev dependencies. + * + * If `true`, packages that have the updated package as a dev + * dependency will also be considered for version updates. + */ + propagateDevDependencies: boolean + /** + * Whether to propagate peer dependencies. + * + * If `true`, packages that have the updated package as a peer + * dependency will also be considered for version updates. + */ + propagatePeerDependencies: boolean + /** + * Maximum propagation depth. + * + * Limits how deep dependency propagation can traverse the + * dependency graph. Prevents excessive updates in large monorepos. + */ + maxDepth: number + /** + * Whether to fail on circular dependencies. + * + * If `true`, the operation fails when circular dependencies are + * detected. If `false`, circular dependencies are handled gracefully. + */ + failOnCircular: boolean + /** + * Skip workspace: protocol dependencies. + * + * If `true`, dependencies using `workspace:` protocol are not + * propagated. These are typically handled differently in monorepos. + */ + skipWorkspaceProtocol: boolean + /** + * Skip file: protocol dependencies. + * + * If `true`, dependencies using `file:` protocol are not propagated. + */ + skipFileProtocol: boolean + /** + * Skip link: protocol dependencies. + * + * If `true`, dependencies using `link:` protocol are not propagated. + */ + skipLinkProtocol: boolean + /** + * Skip portal: protocol dependencies. + * + * If `true`, dependencies using `portal:` protocol are not propagated. + */ + skipPortalProtocol: boolean +} + +/** + * Dependency update information for a package version bump. + * + * This structure captures information about how a dependency version + * was updated as part of the version bump process. Dependencies are + * updated when the package they depend on is bumped. + * + * # Fields + * + * - `name`: The dependency package name + * - `dependency_type`: The type of dependency (regular, dev, peer, optional) + * - `old_version`: The previous version specification + * - `new_version`: The new version specification + * + * # TypeScript Definition + * + * ```typescript + * interface DependencyUpdateInfo { + * name: string; + * dependencyType: 'regular' | 'dev' | 'peer' | 'optional'; + * oldVersion: string; + * newVersion: string; + * } + * ``` + * + * # Examples + * + * ```typescript + * const update: DependencyUpdateInfo = { + * name: '@scope/core', + * dependencyType: 'regular', + * oldVersion: '^1.0.0', + * newVersion: '^1.1.0' + * }; + * ``` + */ +export interface DependencyUpdateInfo { + /** + * The dependency package name. + * + * This is the name of the package that was updated as a dependency. + * May include scope (e.g., `@scope/package`). + */ + name: string + /** + * The type of dependency. + * + * One of: `regular`, `dev`, `peer`, `optional` + */ + dependencyType: string + /** + * The previous version specification. + * + * This is the version range or exact version that was previously + * specified in package.json (e.g., `^1.0.0`, `~1.0.0`, `1.0.0`). + */ + oldVersion: string + /** + * The new version specification. + * + * This is the updated version range or exact version after the bump. + */ + newVersion: string +} + +/** + * Error information structure for Node.js bindings. + * + * This structure is exposed to JavaScript/TypeScript via napi-rs and provides + * detailed error information in a format familiar to Node.js developers. + * The `#[napi(object)]` attribute enables automatic conversion to JavaScript + * objects and TypeScript type generation. + * + * # Fields + * + * - `code`: Node.js-style error code (e.g., "EVALIDATION", "EGIT") + * - `message`: Human-readable error message + * - `context`: Optional additional context (field name, path, etc.) + * - `kind`: Error category from the CLI layer + * + * # TypeScript Definition + * + * ```typescript + * export interface ErrorInfo { + * Node.js-style error code (e.g., "EVALIDATION", "EGIT") + * code: string; + * Human-readable error message + * message: string; + * Optional additional context about the error + * context?: string; + * Error category from CLI (for debugging) + * kind: string; + * } + * ``` + * + * # Examples + * + * ```typescript + * // In JavaScript/TypeScript: + * if (!result.success) { + * const { code, message, context, kind } = result.error; + * console.error(`[${code}] ${message}`); + * if (context) { + * console.error(`Context: ${context}`); + * } + * } + * ``` + */ +export interface ErrorInfo { + /** + * Node.js-style error code (e.g., "EVALIDATION", "EGIT"). + * + * These codes follow Node.js conventions and can be used for + * programmatic error handling in JavaScript/TypeScript. + * + * # Available Codes + * + * - `ECONFIG`: Configuration errors + * - `EVALIDATION`: Validation errors + * - `EEXEC`: Execution errors + * - `EGIT`: Git errors + * - `EPKG`: Package errors + * - `ENOENT`: File/path not found + * - `EIO`: I/O errors + * - `ENETWORK`: Network errors + * - `EUSER`: User errors + * - `ETIMEOUT`: Timeout errors + */ + code: string + /** + * Human-readable error message. + * + * This message is suitable for displaying to end users and + * provides a clear description of what went wrong. + */ + message: string + /** + * Optional additional context for the error. * * This may contain the field name that caused a validation error, * the path that was not found, or other relevant context information. @@ -3242,6 +4190,54 @@ export interface ExecuteApiResponse { error?: ErrorInfo | undefined } +/** + * Execute configuration information. + * + * Contains settings for command execution with timeout and parallelism. + * + * # Fields + * + * - `timeout_secs`: Overall timeout in seconds + * - `per_package_timeout_secs`: Per-package timeout in seconds + * - `max_parallel`: Maximum number of parallel executions + * + * # TypeScript Definition + * + * ```typescript + * interface ExecuteConfigInfo { + * // Overall timeout in seconds (0 = no timeout) + * timeoutSecs: number; + * // Per-package timeout in seconds (0 = no timeout) + * perPackageTimeoutSecs: number; + * // Maximum number of parallel executions + * maxParallel: number; + * } + * ``` + */ +export interface ExecuteConfigInfo { + /** + * Overall timeout in seconds. + * + * Maximum time allowed for the entire execute command. + * A value of 0 means no timeout. + */ + timeoutSecs: number + /** + * Per-package timeout in seconds. + * + * Maximum time allowed for executing the command on each package. + * A value of 0 means no timeout. + */ + perPackageTimeoutSecs: number + /** + * Maximum number of parallel executions. + * + * How many packages can have commands running simultaneously. + * Higher values can speed up execution but increase resource usage. + */ + maxParallel: number +} + /** * Execute command response data. * @@ -3592,6 +4588,95 @@ export interface ExecuteSummary { */ export declare function getVersion(): string +/** + * Git configuration information. + * + * Contains settings for Git integration. + * + * # Fields + * + * - `branch_base`: Base branch for comparisons + * - `detect_affected_packages`: Whether to auto-detect affected packages + * + * # TypeScript Definition + * + * ```typescript + * interface GitConfigInfo { + * // Base branch for comparisons (e.g., "main", "master") + * branchBase: string; + * // Whether to auto-detect affected packages from Git changes + * detectAffectedPackages: boolean; + * } + * ``` + */ +export interface GitConfigInfo { + /** + * Base branch for comparisons. + * + * The branch used as the base for determining changes. + * Common values: "main", "master", "develop". + */ + branchBase: string + /** + * Whether to auto-detect affected packages. + * + * If `true`, packages affected by Git changes are automatically + * detected based on file changes. + */ + detectAffectedPackages: boolean +} + +/** + * Health score weights configuration. + * + * Contains weights for calculating the overall health score. + * + * # TypeScript Definition + * + * ```typescript + * interface HealthScoreWeightsInfo { + * // Weight for upgrade score (0.0-1.0) + * upgradesWeight: number; + * // Weight for dependencies score (0.0-1.0) + * dependenciesWeight: number; + * // Weight for version consistency score (0.0-1.0) + * versionConsistencyWeight: number; + * // Weight for breaking changes score (0.0-1.0) + * breakingChangesWeight: number; + * } + * ``` + */ +export interface HealthScoreWeightsInfo { + /** + * Weight for upgrade score. + * + * How much the upgrade status contributes to the health score. + * Value between 0.0 and 1.0. + */ + upgradesWeight: number + /** + * Weight for dependencies score. + * + * How much the dependency health contributes to the health score. + * Value between 0.0 and 1.0. + */ + dependenciesWeight: number + /** + * Weight for version consistency score. + * + * How much version consistency contributes to the health score. + * Value between 0.0 and 1.0. + */ + versionConsistencyWeight: number + /** + * Weight for breaking changes score. + * + * How much breaking changes impact the health score. + * Value between 0.0 and 1.0. + */ + breakingChangesWeight: number +} + /** * Initialize a workspace with changeset-based version management. * @@ -4319,6 +5404,72 @@ export interface PackageVersionInfo { dependencyUpdates: Array } +/** + * Registry configuration information. + * + * Contains settings for NPM registry access. + * + * # Fields + * + * - `default_registry`: Default npm registry URL + * - `scoped_registries`: Map of scopes to registry URLs + * - `timeout_secs`: Request timeout in seconds + * - `retry_attempts`: Number of retry attempts for failed requests + * - `read_npmrc`: Whether to read .npmrc for registry configuration + * + * # TypeScript Definition + * + * ```typescript + * interface RegistryConfigInfo { + * // Default npm registry URL + * defaultRegistry: string; + * // Map of scopes to registry URLs (e.g., {"@myorg": "https://npm.myorg.com"}) + * scopedRegistries: Record; + * // Request timeout in seconds + * timeoutSecs: number; + * // Number of retry attempts for failed requests + * retryAttempts: number; + * // Whether to read .npmrc for registry configuration + * readNpmrc: boolean; + * } + * ``` + */ +export interface RegistryConfigInfo { + /** + * Default npm registry URL. + * + * The registry URL to use for packages without a specific scope + * configuration. Default is "https://registry.npmjs.org". + */ + defaultRegistry: string + /** + * Map of scopes to registry URLs. + * + * Allows configuring different registries for different npm scopes. + * Keys are scope names (e.g., "@myorg"), values are registry URLs. + */ + scopedRegistries: Record + /** + * Request timeout in seconds. + * + * How long to wait for registry requests before timing out. + */ + timeoutSecs: number + /** + * Number of retry attempts for failed requests. + * + * How many times to retry a failed registry request before giving up. + */ + retryAttempts: number + /** + * Whether to read .npmrc for registry configuration. + * + * If `true`, the tool will read `.npmrc` files for additional + * registry configuration and authentication tokens. + */ + readNpmrc: boolean +} + /** * Entry in the released versions map. * @@ -4444,6 +5595,42 @@ export interface RepositoryInfo { monorepoType?: string | undefined } +/** + * Scoped registry entry. + * + * Represents a mapping from an npm scope to a registry URL. + * + * # Fields + * + * - `scope`: The npm scope (e.g., "@myorg") + * - `registry`: The registry URL for this scope + * + * # TypeScript Definition + * + * ```typescript + * interface ScopedRegistryEntry { + * // The npm scope (e.g., "@myorg") + * scope: string; + * // The registry URL for this scope + * registry: string; + * } + * ``` + */ +export interface ScopedRegistryEntry { + /** + * The npm scope. + * + * The scope name including the `@` prefix (e.g., "@myorg"). + */ + scope: string + /** + * The registry URL for this scope. + * + * The full URL of the npm registry to use for this scope. + */ + registry: string +} + /** * Snapshot version information for a package. * @@ -4824,3 +6011,112 @@ export interface UpdateSummaryInfo { */ environmentsAdded: number } + +/** + * Upgrade configuration information. + * + * Contains settings for upgrade detection and application. + * + * # Fields + * + * - `auto_changeset`: Automatically create changesets for upgrades + * - `changeset_bump`: Version bump type for upgrade changesets + * - `registry`: Registry configuration + * - `backup`: Backup configuration + * + * # TypeScript Definition + * + * ```typescript + * interface UpgradeConfigInfo { + * // Automatically create changesets for upgrades + * autoChangeset: boolean; + * // Version bump type for upgrade changesets + * changesetBump: string; + * // Registry configuration + * registry: RegistryConfigInfo; + * // Backup configuration + * backup: BackupConfigInfo; + * } + * ``` + */ +export interface UpgradeConfigInfo { + /** + * Automatically create changesets for upgrades. + * + * If `true`, a changeset is automatically created when + * dependency upgrades are applied. + */ + autoChangeset: boolean + /** + * Version bump type for upgrade changesets. + * + * The bump type to use when creating changesets for upgrades. + * Values: "major", "minor", "patch", "none". + */ + changesetBump: string + /** + * Registry configuration. + * + * Settings for accessing npm registries to check for updates. + */ + registry: RegistryConfigInfo + /** + * Backup configuration. + * + * Settings for backup and rollback functionality. + */ + backup: BackupConfigInfo +} + +/** + * Version configuration information. + * + * Contains settings for version resolution and management. + * + * # Fields + * + * - `strategy`: Versioning strategy ("independent" or "unified") + * - `default_bump`: Default version bump type + * - `snapshot_format`: Format template for snapshot versions + * + * # TypeScript Definition + * + * ```typescript + * interface VersionConfigInfo { + * // Versioning strategy: "independent" or "unified" + * strategy: string; + * // Default version bump type: "major", "minor", "patch", or "none" + * defaultBump: string; + * // Format template for snapshot versions + * snapshotFormat: string; + * } + * ``` + */ +export interface VersionConfigInfo { + /** + * Versioning strategy. + * + * Determines how package versions are managed: + * - `"independent"`: Each package has its own version + * - `"unified"`: All packages share the same version + */ + strategy: string + /** + * Default version bump type. + * + * Used when no explicit bump type is specified: + * - `"major"`: Breaking changes + * - `"minor"`: New features + * - `"patch"`: Bug fixes + * - `"none"`: No version change + */ + defaultBump: string + /** + * Format template for snapshot versions. + * + * Template string for generating snapshot version identifiers. + * Supports placeholders like `{version}`, `{branch}`, `{commit}`, + * `{shortCommit}`, and `{timestamp}`. + */ + snapshotFormat: string +} diff --git a/packages/workspace-tools/src/binding.js b/packages/workspace-tools/src/binding.js index a733f709..e0355b13 100644 --- a/packages/workspace-tools/src/binding.js +++ b/packages/workspace-tools/src/binding.js @@ -77,8 +77,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-android-arm64') const bindingPackageVersion = require('@websublime/workspace-tools-android-arm64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -93,8 +93,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-android-arm-eabi') const bindingPackageVersion = require('@websublime/workspace-tools-android-arm-eabi/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -114,8 +114,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-win32-x64-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-win32-x64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -130,8 +130,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-win32-x64-msvc') const bindingPackageVersion = require('@websublime/workspace-tools-win32-x64-msvc/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -147,8 +147,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-win32-ia32-msvc') const bindingPackageVersion = require('@websublime/workspace-tools-win32-ia32-msvc/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -163,8 +163,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-win32-arm64-msvc') const bindingPackageVersion = require('@websublime/workspace-tools-win32-arm64-msvc/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -182,8 +182,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-darwin-universal') const bindingPackageVersion = require('@websublime/workspace-tools-darwin-universal/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -198,8 +198,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-darwin-x64') const bindingPackageVersion = require('@websublime/workspace-tools-darwin-x64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -214,8 +214,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-darwin-arm64') const bindingPackageVersion = require('@websublime/workspace-tools-darwin-arm64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -234,8 +234,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-freebsd-x64') const bindingPackageVersion = require('@websublime/workspace-tools-freebsd-x64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -250,8 +250,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-freebsd-arm64') const bindingPackageVersion = require('@websublime/workspace-tools-freebsd-arm64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -271,8 +271,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-x64-musl') const bindingPackageVersion = require('@websublime/workspace-tools-linux-x64-musl/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -287,8 +287,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-x64-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-linux-x64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -305,8 +305,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-arm64-musl') const bindingPackageVersion = require('@websublime/workspace-tools-linux-arm64-musl/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -321,8 +321,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-arm64-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-linux-arm64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -339,8 +339,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-arm-musleabihf') const bindingPackageVersion = require('@websublime/workspace-tools-linux-arm-musleabihf/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -355,8 +355,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-arm-gnueabihf') const bindingPackageVersion = require('@websublime/workspace-tools-linux-arm-gnueabihf/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -373,8 +373,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-loong64-musl') const bindingPackageVersion = require('@websublime/workspace-tools-linux-loong64-musl/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -389,8 +389,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-loong64-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-linux-loong64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -407,8 +407,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-riscv64-musl') const bindingPackageVersion = require('@websublime/workspace-tools-linux-riscv64-musl/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -423,8 +423,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-riscv64-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-linux-riscv64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -440,8 +440,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-ppc64-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-linux-ppc64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -456,8 +456,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-linux-s390x-gnu') const bindingPackageVersion = require('@websublime/workspace-tools-linux-s390x-gnu/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -476,8 +476,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-openharmony-arm64') const bindingPackageVersion = require('@websublime/workspace-tools-openharmony-arm64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -492,8 +492,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-openharmony-x64') const bindingPackageVersion = require('@websublime/workspace-tools-openharmony-x64/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -508,8 +508,8 @@ function requireNative() { try { const binding = require('@websublime/workspace-tools-openharmony-arm') const bindingPackageVersion = require('@websublime/workspace-tools-openharmony-arm/package.json').version - if (bindingPackageVersion !== '2.0.18' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.18 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.19' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.19 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { From 912ceaa645162e24bf654978ecc6fd74256680e7 Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:44:44 +0000 Subject: [PATCH 5/7] feat(WOR-TSK-202): export config types from index.ts Update public API exports to include all config types: Input Parameters: - ConfigShowParams, ConfigValidateParams Response Data: - ConfigShowData, ConfigValidateData API Responses: - ConfigShowApiResponse, ConfigValidateApiResponse Validation Types: - ConfigValidationIssue Main Configuration: - ConfigData Configuration Sections: - ChangesetConfigInfo, VersionConfigInfo - DependencyConfigInfo, UpgradeConfigInfo - RegistryConfigInfo, ScopedRegistryEntry - BackupConfigInfo, ChangelogConfigInfo - AuditConfigInfo, AuditSectionsConfigInfo - HealthScoreWeightsInfo, GitConfigInfo - ExecuteConfigInfo --- packages/workspace-tools/src/index.ts | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/workspace-tools/src/index.ts b/packages/workspace-tools/src/index.ts index 31abf9f9..28542313 100644 --- a/packages/workspace-tools/src/index.ts +++ b/packages/workspace-tools/src/index.ts @@ -22,6 +22,12 @@ * - `bumpSnapshot()` - Generate snapshot versions for testing and CI (Story 5.4) * - `execute()` - Execute commands across workspace packages with timeout support (Story 6.3) * + * Config types (Story 7.1): + * - `ConfigShowParams`, `ConfigShowData`, `ConfigShowApiResponse` + * - `ConfigValidateParams`, `ConfigValidateData`, `ConfigValidateApiResponse` + * - `ConfigData`, `ConfigValidationIssue` + * - Configuration section types: `ChangesetConfigInfo`, `VersionConfigInfo`, `DependencyConfigInfo`, etc. + * * Bump types (Story 5.1): * - `BumpPreviewParams`, `BumpPreviewData`, `BumpPreviewApiResponse` * - `BumpApplyParams`, `BumpApplyData`, `BumpApplyApiResponse` @@ -177,4 +183,38 @@ export type { // Supporting types PackageExecutionResult, ExecuteSummary, + + // Config command types (Story 7.1) + // Input parameters + ConfigShowParams, + ConfigValidateParams, + + // Response data + ConfigShowData, + ConfigValidateData, + + // API responses + ConfigShowApiResponse, + ConfigValidateApiResponse, + + // Validation types + ConfigValidationIssue, + + // Main configuration container + ConfigData, + + // Configuration section types + ChangesetConfigInfo, + VersionConfigInfo, + DependencyConfigInfo, + UpgradeConfigInfo, + RegistryConfigInfo, + ScopedRegistryEntry, + BackupConfigInfo, + ChangelogConfigInfo, + AuditConfigInfo, + AuditSectionsConfigInfo, + HealthScoreWeightsInfo, + GitConfigInfo, + ExecuteConfigInfo, } from './binding' From 72e26823b31dd9a8a11aa414634fe3d3308c8784 Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:44:51 +0000 Subject: [PATCH 6/7] chore(WOR-TSK-202): sync npm package versions Run napi version to synchronize platform-specific package versions with the main workspace-tools package. --- packages/workspace-tools/npm/darwin-arm64/package.json | 2 +- packages/workspace-tools/npm/darwin-x64/package.json | 2 +- packages/workspace-tools/npm/linux-arm64-gnu/package.json | 2 +- packages/workspace-tools/npm/linux-arm64-musl/package.json | 2 +- packages/workspace-tools/npm/linux-x64-gnu/package.json | 2 +- packages/workspace-tools/npm/linux-x64-musl/package.json | 2 +- packages/workspace-tools/npm/win32-arm64-msvc/package.json | 2 +- packages/workspace-tools/npm/win32-x64-msvc/package.json | 2 +- packages/workspace-tools/package.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/workspace-tools/npm/darwin-arm64/package.json b/packages/workspace-tools/npm/darwin-arm64/package.json index 945f17bf..cdea4f3e 100644 --- a/packages/workspace-tools/npm/darwin-arm64/package.json +++ b/packages/workspace-tools/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-darwin-arm64", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "arm64" ], diff --git a/packages/workspace-tools/npm/darwin-x64/package.json b/packages/workspace-tools/npm/darwin-x64/package.json index b79d10d3..8e2488e3 100644 --- a/packages/workspace-tools/npm/darwin-x64/package.json +++ b/packages/workspace-tools/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-darwin-x64", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "x64" ], diff --git a/packages/workspace-tools/npm/linux-arm64-gnu/package.json b/packages/workspace-tools/npm/linux-arm64-gnu/package.json index 0fa51deb..101769c8 100644 --- a/packages/workspace-tools/npm/linux-arm64-gnu/package.json +++ b/packages/workspace-tools/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-linux-arm64-gnu", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "arm64" ], diff --git a/packages/workspace-tools/npm/linux-arm64-musl/package.json b/packages/workspace-tools/npm/linux-arm64-musl/package.json index c6151e8f..e9e6319c 100644 --- a/packages/workspace-tools/npm/linux-arm64-musl/package.json +++ b/packages/workspace-tools/npm/linux-arm64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-linux-arm64-musl", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "arm64" ], diff --git a/packages/workspace-tools/npm/linux-x64-gnu/package.json b/packages/workspace-tools/npm/linux-x64-gnu/package.json index 35d8668b..a216fb98 100644 --- a/packages/workspace-tools/npm/linux-x64-gnu/package.json +++ b/packages/workspace-tools/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-linux-x64-gnu", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "x64" ], diff --git a/packages/workspace-tools/npm/linux-x64-musl/package.json b/packages/workspace-tools/npm/linux-x64-musl/package.json index 956b8432..57f2f93d 100644 --- a/packages/workspace-tools/npm/linux-x64-musl/package.json +++ b/packages/workspace-tools/npm/linux-x64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-linux-x64-musl", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "x64" ], diff --git a/packages/workspace-tools/npm/win32-arm64-msvc/package.json b/packages/workspace-tools/npm/win32-arm64-msvc/package.json index ab678859..b92b848e 100644 --- a/packages/workspace-tools/npm/win32-arm64-msvc/package.json +++ b/packages/workspace-tools/npm/win32-arm64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-win32-arm64-msvc", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "arm64" ], diff --git a/packages/workspace-tools/npm/win32-x64-msvc/package.json b/packages/workspace-tools/npm/win32-x64-msvc/package.json index 7ad12302..0348e086 100644 --- a/packages/workspace-tools/npm/win32-x64-msvc/package.json +++ b/packages/workspace-tools/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools-win32-x64-msvc", - "version": "2.0.18", + "version": "2.0.19", "cpu": [ "x64" ], diff --git a/packages/workspace-tools/package.json b/packages/workspace-tools/package.json index 337c37af..266d6b5e 100644 --- a/packages/workspace-tools/package.json +++ b/packages/workspace-tools/package.json @@ -1,6 +1,6 @@ { "name": "@websublime/workspace-tools", - "version": "2.0.18", + "version": "2.0.19", "description": "Bindings for node from crate workspace-tools", "main": "./dist/cjs/index.cjs", "types": "./dist/types/index.d.cts", From a885351fb7f124e5eebb544f2b0dc1cdeb2a947a Mon Sep 17 00:00:00 2001 From: Sublime Git Bot Date: Tue, 16 Dec 2025 05:52:21 +0000 Subject: [PATCH 7/7] style(WOR-TSK-202): fix import ordering and clippy warnings Apply cargo fmt to fix import ordering in tests.rs. Fix clippy::field_reassign_with_default by using struct update syntax instead of mutable reassignment after Default::default(). --- crates/node/src/tests.rs | 23 ++++++++++++----------- crates/node/src/types/mod.rs | 8 ++++---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/crates/node/src/tests.rs b/crates/node/src/tests.rs index 574e4819..6e33ddae 100644 --- a/crates/node/src/tests.rs +++ b/crates/node/src/tests.rs @@ -31,7 +31,7 @@ /// Tests for lib.rs version functions and constants. #[cfg(test)] mod version_tests { - use crate::{get_version, VERSION}; + use crate::{VERSION, get_version}; #[test] #[allow(clippy::const_is_empty)] @@ -820,7 +820,7 @@ mod validation_tests { #[cfg(test)] mod response_tests { use crate::error::ErrorInfo; - use crate::response::{result_to_response, ApiResponse, ApiResponseExt, JsonResponse}; + use crate::response::{ApiResponse, ApiResponseExt, JsonResponse, result_to_response}; use serde::Serialize; use std::io::{Error as IoError, ErrorKind}; use sublime_cli_tools::error::CliError; @@ -3360,9 +3360,8 @@ mod bump_types_tests { use crate::types::bump::{ BumpApplyApiResponse, BumpApplyData, BumpApplyParams, BumpPreviewApiResponse, BumpPreviewData, BumpPreviewParams, BumpSnapshotApiResponse, BumpSnapshotData, - BumpSnapshotParams, BumpSummaryInfo, DependencyUpdateInfo, PackageVersionInfo, - SnapshotVersionInfo, COMMON_PRERELEASE_TAGS, DEFAULT_SNAPSHOT_FORMAT, - VALID_DEPENDENCY_TYPES, + BumpSnapshotParams, BumpSummaryInfo, COMMON_PRERELEASE_TAGS, DEFAULT_SNAPSHOT_FORMAT, + DependencyUpdateInfo, PackageVersionInfo, SnapshotVersionInfo, VALID_DEPENDENCY_TYPES, }; // ======================================================================== @@ -5585,12 +5584,14 @@ mod config_scenario_tests { assert_eq!(params.root, "/path/to/workspace"); // Simulate loaded config with custom version strategy - let mut config = ConfigData::default(); - config.version = VersionConfigInfo::new( - "unified".to_string(), - "minor".to_string(), - "{version}-dev".to_string(), - ); + let config = ConfigData { + version: VersionConfigInfo::new( + "unified".to_string(), + "minor".to_string(), + "{version}-dev".to_string(), + ), + ..Default::default() + }; let show_data = ConfigShowData::new( "/path/to/workspace/repo.config.json".to_string(), diff --git a/crates/node/src/types/mod.rs b/crates/node/src/types/mod.rs index b89083eb..0fedcaa1 100644 --- a/crates/node/src/types/mod.rs +++ b/crates/node/src/types/mod.rs @@ -106,13 +106,13 @@ pub(crate) use config::{ RegistryConfigInfo, ScopedRegistryEntry, UpgradeConfigInfo, - VersionConfigInfo, // Constants VALID_BUMP_TYPES, VALID_CHANGELOG_FORMATS, VALID_MONOREPO_MODES, VALID_SEVERITY_LEVELS, VALID_STRATEGIES as CONFIG_VALID_STRATEGIES, + VersionConfigInfo, }; // Changeset types (Story 4.1 - Implemented) @@ -176,13 +176,13 @@ pub(crate) use bump::{ BumpSnapshotData, BumpSnapshotParams, BumpSummaryInfo, + // Constants + COMMON_PRERELEASE_TAGS, + DEFAULT_SNAPSHOT_FORMAT, DependencyUpdateInfo, // Supporting Types PackageVersionInfo, SnapshotVersionInfo, - // Constants - COMMON_PRERELEASE_TAGS, - DEFAULT_SNAPSHOT_FORMAT, VALID_DEPENDENCY_TYPES, };