Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Zod for Robust Configuration Validation #77

Closed
wants to merge 4 commits into from

Conversation

yamadashy
Copy link
Owner

@yamadashy yamadashy commented Sep 15, 2024

  • Implement Zod for Robust Configuration Validation
  • Progress Logging Enhancement

Summary by CodeRabbit

  • New Features

    • Enhanced logging visibility by including file paths in progress messages for packaging processes.
    • Introduced robust error handling for configuration validation, improving clarity on configuration-related issues.
    • Added a new dependency, Zod, to improve data validation and schema management.
  • Refactor

    • Improved code organization by extracting CLI options parsing into a dedicated function, enhancing maintainability and clarity.
    • Updated configuration management to utilize schema validation, ensuring more reliable and predictable configuration handling.
    • Reorganized configuration types to a schema-based approach for enhanced clarity and maintainability.

Copy link
Contributor

coderabbitai bot commented Sep 15, 2024

Walkthrough

The changes involve updates to the project's configuration management and error handling by integrating the Zod library for schema validation. The package.json file now includes a new dependency on zod, while several files have been refactored to utilize this library for enhanced validation. Additionally, import statements have been updated to reflect the new schema organization, and several tests have been added or modified to ensure robust configuration handling.

Changes

Files Change Summary
package.json Added dependency on zod with version ^3.23.8.
src/cli/actions/defaultActionRunner.ts Refactored runDefaultAction to extract CLI options parsing into buildCliConfig.
src/cli/actions/initActionRunner.ts, src/cli/cliPrinter.ts, src/cli/cliRunner.ts Updated import statements to source types from configSchema.js instead of configTypes.js.
src/config/configLoader.ts Integrated Zod for schema validation in loadAndValidateConfig and mergeConfigs.
src/config/configSchema.ts Introduced new schema definitions using Zod for configuration management.
src/config/configTypes.ts, src/config/configValidator.ts Deleted files containing old type definitions and validation logic.
src/config/defaultConfig.ts Modified defaultConfig to use schema validation with repopackConfigDefaultSchema.parse().
src/core/file/fileProcessor.ts, src/core/file/fileSearcher.ts, src/core/output/outputGenerator.ts, src/core/output/outputGeneratorTypes.ts, src/core/output/outputStyleDecorator.ts Updated import statements to source RepopackConfigMerged from configSchema.js.
src/index.ts Changed export statement for RepopackConfig type to come from configSchema.js.
src/shared/errorHandler.ts Added RepopackConfigValidationError class and rethrowValidationErrorIfZodError function for error handling.
tests/config/configLoader.test.ts Enhanced tests to verify validation and error handling for configuration loading and merging.
tests/config/configValidator.test.ts Deleted tests related to the old validation logic.
tests/integration-tests/packager.test.ts, tests/testing/testUtils.ts Updated import paths for configuration types to configSchema.js.

Possibly related PRs

  • chore(deps): update all non-major dependencies #78: The changes in package.json related to updating dependencies are relevant as they involve modifications to the same file, indicating a direct connection to the main PR's changes in the dependencies section.

Suggested labels

renovate, dependencies


Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between aec2be6 and b9e39b1.

Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
Files selected for processing (23)
  • package.json (2 hunks)
  • src/cli/actions/defaultActionRunner.ts (3 hunks)
  • src/cli/actions/initActionRunner.ts (1 hunks)
  • src/cli/cliPrinter.ts (1 hunks)
  • src/cli/cliRunner.ts (1 hunks)
  • src/config/configLoader.ts (3 hunks)
  • src/config/configSchema.ts (1 hunks)
  • src/config/configTypes.ts (0 hunks)
  • src/config/configValidator.ts (0 hunks)
  • src/config/defaultConfig.ts (2 hunks)
  • src/core/file/fileProcessor.ts (1 hunks)
  • src/core/file/fileSearcher.ts (1 hunks)
  • src/core/output/outputGenerator.ts (1 hunks)
  • src/core/output/outputGeneratorTypes.ts (1 hunks)
  • src/core/output/outputStyleDecorator.ts (1 hunks)
  • src/core/packager.ts (2 hunks)
  • src/core/security/securityCheckRunner.ts (2 hunks)
  • src/index.ts (1 hunks)
  • src/shared/errorHandler.ts (3 hunks)
  • tests/config/configLoader.test.ts (4 hunks)
  • tests/config/configValidator.test.ts (0 hunks)
  • tests/integration-tests/packager.test.ts (1 hunks)
  • tests/testing/testUtils.ts (1 hunks)
Files not reviewed due to no reviewable changes (3)
  • src/config/configTypes.ts
  • src/config/configValidator.ts
  • tests/config/configValidator.test.ts
Files skipped from review as they are similar to previous changes (20)
  • package.json
  • src/cli/actions/defaultActionRunner.ts
  • src/cli/actions/initActionRunner.ts
  • src/cli/cliPrinter.ts
  • src/cli/cliRunner.ts
  • src/config/configLoader.ts
  • src/config/configSchema.ts
  • src/config/defaultConfig.ts
  • src/core/file/fileProcessor.ts
  • src/core/file/fileSearcher.ts
  • src/core/output/outputGenerator.ts
  • src/core/output/outputGeneratorTypes.ts
  • src/core/output/outputStyleDecorator.ts
  • src/core/packager.ts
  • src/core/security/securityCheckRunner.ts
  • src/index.ts
  • src/shared/errorHandler.ts
  • tests/config/configLoader.test.ts
  • tests/integration-tests/packager.test.ts
  • tests/testing/testUtils.ts

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    -- I pushed a fix in commit <commit_id>, please review it.
    -- Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Tip

Early access features: enabled

We are currently testing new code review model(s) that may lead to higher noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

@yamadashy yamadashy changed the title Refactor CLI config building and improve progress logging Implement Zod for Robust Configuration Validation and improve progress logging Sep 15, 2024
@yamadashy yamadashy changed the title Implement Zod for Robust Configuration Validation and improve progress logging Implement Zod for Robust Configuration Validation Sep 15, 2024
Repository owner deleted a comment from coderabbitai bot Sep 15, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Outside diff range comments (3)
src/core/file/fileSearcher.ts (3)

Line range hint 36-39: Include original error message when throwing a new error

In the catch block, the code logs the original error but throws a new generic error message. Including the original error message in the thrown error can provide more context and aid in debugging.

Apply this diff to include the original error message:

     logger.error('Error filtering files:', error);
-    throw new Error('Failed to filter files');
+    throw new Error(`Failed to filter files: ${error.message}`);

Line range hint 48-58: Remove unnecessary 'async' keyword from 'getIgnoreFilePatterns'

The function getIgnoreFilePatterns is declared as async but does not contain any await expressions or perform asynchronous operations. This is unnecessary and can be misleading.

Apply this diff to remove the async keyword:

-export const getIgnoreFilePatterns = async (config: RepopackConfigMerged): Promise<string[]> => {
+export const getIgnoreFilePatterns = (config: RepopackConfigMerged): Promise<string[]> => {

Line range hint 60-82: Remove unnecessary 'async' keyword from 'getIgnorePatterns'

Similarly, the function getIgnorePatterns does not perform any asynchronous operations and doesn't require the async keyword.

Apply this diff to remove the async keyword:

-export const getIgnorePatterns = async (rootDir: string, config: RepopackConfigMerged): Promise<string[]> => {
+export const getIgnorePatterns = (rootDir: string, config: RepopackConfigMerged): Promise<string[]> => {
Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 6546967 and aec2be6.

Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
Files selected for processing (23)
  • package.json (2 hunks)
  • src/cli/actions/defaultActionRunner.ts (3 hunks)
  • src/cli/actions/initActionRunner.ts (1 hunks)
  • src/cli/cliPrinter.ts (1 hunks)
  • src/cli/cliRunner.ts (1 hunks)
  • src/config/configLoader.ts (3 hunks)
  • src/config/configSchema.ts (1 hunks)
  • src/config/configTypes.ts (0 hunks)
  • src/config/configValidator.ts (0 hunks)
  • src/config/defaultConfig.ts (2 hunks)
  • src/core/file/fileProcessor.ts (1 hunks)
  • src/core/file/fileSearcher.ts (1 hunks)
  • src/core/output/outputGenerator.ts (1 hunks)
  • src/core/output/outputGeneratorTypes.ts (1 hunks)
  • src/core/output/outputStyleDecorator.ts (1 hunks)
  • src/core/packager.ts (2 hunks)
  • src/core/security/securityCheckRunner.ts (2 hunks)
  • src/index.ts (1 hunks)
  • src/shared/errorHandler.ts (3 hunks)
  • tests/config/configLoader.test.ts (4 hunks)
  • tests/config/configValidator.test.ts (0 hunks)
  • tests/integration-tests/packager.test.ts (1 hunks)
  • tests/testing/testUtils.ts (1 hunks)
Files not reviewed due to no reviewable changes (3)
  • src/config/configTypes.ts
  • src/config/configValidator.ts
  • tests/config/configValidator.test.ts
Additional comments not posted (27)
src/index.ts (1)

2-2: Verify the export of RepopackConfigFile from configSchema.js.

The export statement now imports RepopackConfigFile from ./config/configSchema.js instead of ./config/configTypes.js and re-exports it as RepopackConfig. Ensure that RepopackConfigFile is correctly exported from configSchema.js and that all references to RepopackConfig remain valid throughout the codebase.

Run the following script to confirm that RepopackConfigFile is exported from configSchema.js:

Additionally, verify that no imports are still referencing ./config/configTypes.js:

Verification successful

Verification successful: Export of RepopackConfigFile is correct

The verification process has confirmed that the changes mentioned in the review comment are correct and properly implemented:

  • RepopackConfigFile is correctly exported from src/config/configSchema.ts.
  • There are no remaining references to configTypes.js in the codebase.
  • The export statement in src/index.ts correctly re-exports RepopackConfigFile as RepopackConfig from ./config/configSchema.js.

These changes ensure that all references to RepopackConfig remain valid throughout the codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that RepopackConfigFile is exported from configSchema.js

# Test: Search for the export of RepopackConfigFile. Expect: Export statement is found.
rg --type=typescript 'export\s+(interface|type)\s+RepopackConfigFile' ./src/config/configSchema.ts

Length of output: 135


Script:

#!/bin/bash
# Description: Check for lingering imports from configTypes.js

# Test: Search for imports from configTypes.js. Expect: No matches found.
rg --type=typescript 'from\s+["'"]\.\/config\/configTypes\.js["'"]'

Length of output: 184


Script:

#!/bin/bash
# List all .ts and .js files in the src/config directory
echo "Listing .ts and .js files in src/config:"
fd -e ts -e js . src/config

# Check for export of RepopackConfigFile in configSchema.js
echo "Checking for export of RepopackConfigFile:"
ast-grep --lang typescript --pattern 'export type RepopackConfigFile = $_' src/config/configSchema.js

# Check for any remaining imports from configTypes.js
echo "Checking for imports from configTypes.js:"
ast-grep --lang typescript --pattern 'import $_ from "./config/configTypes.js"'

# Check for any usage of RepopackConfig
echo "Checking for usage of RepopackConfig:"
ast-grep --lang typescript --pattern 'RepopackConfig'

Length of output: 948


Script:

#!/bin/bash
# Check for export of RepopackConfigFile in configSchema.ts
echo "Checking for export of RepopackConfigFile in configSchema.ts:"
ast-grep --lang typescript --pattern 'export type RepopackConfigFile = $_' src/config/configSchema.ts

# Double-check for any remaining references to configTypes.js
echo "Checking for any references to configTypes.js:"
rg "configTypes\.js"

# Verify the content of src/index.ts
echo "Content of src/index.ts:"
cat src/index.ts

Length of output: 723

src/core/output/outputGeneratorTypes.ts (1)

1-1: Import path correctly updated to reflect new configuration schema

The import statement for RepopackConfigMerged has been appropriately updated to '../../config/configSchema.js', consistent with the integration of Zod for configuration validation. This ensures that the OutputGeneratorContext interface references the correct type definitions from the updated schema.

src/config/defaultConfig.ts (2)

1-1: Import statement correctly includes schema for validation

The addition of repopackConfigDefaultSchema in the import statement ensures that the schema is available for validating the default configuration.


Line range hint 3-21: Robust default configuration validation implemented

Using repopackConfigDefaultSchema.parse({...}) to parse and validate the defaultConfig enhances the robustness of your configuration handling. This ensures that any changes to the default configuration are immediately checked against the schema, reducing the risk of runtime errors due to misconfigurations.

tests/testing/testUtils.ts (1)

3-3: Verify that all imports of RepopackConfigMerged are updated to configSchema.js

The type RepopackConfigMerged is now imported from configSchema.js instead of configTypes.js. Please ensure that RepopackConfigMerged is correctly exported from configSchema.js and that all other files have updated their import statements accordingly to prevent any type resolution issues.

Run the following script to check for any remaining imports from configTypes.js:

Verification successful

Verification successful: All imports of RepopackConfigMerged are correctly updated

The changes to import RepopackConfigMerged from configSchema.js have been successfully implemented across the codebase. Here's a summary of the findings:

  • No remaining imports of RepopackConfigMerged from configTypes.js were found.
  • The type RepopackConfigMerged is correctly exported from src/config/configSchema.ts.
  • Multiple files now import RepopackConfigMerged from configSchema.js, indicating consistent updates throughout the project.

The discrepancy between the .ts file extension of the actual file and the .js extension in import statements is normal in TypeScript projects and doesn't cause any issues.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any import statements of 'RepopackConfigMerged' from 'configTypes.js'

# Expected result: No matches should be found, indicating all imports have been updated.

rg --type typescript "import.*\{.*RepopackConfigMerged.*\}.*from.*configTypes\.js"

Length of output: 119


Script:

#!/bin/bash

# Search for any remaining imports of 'RepopackConfigMerged' from 'configTypes.js'
echo "Searching for imports from configTypes.js:"
rg "import.*\{.*RepopackConfigMerged.*\}.*from.*['\"].*configTypes\.js['\"]" --type-add 'ts:*.{ts,js}'

# Check if 'RepopackConfigMerged' is exported from 'configSchema.js'
echo -e "\nChecking exports in configSchema.js:"
rg "export.*type.*RepopackConfigMerged" src/config/configSchema.js

# Search for updated imports of 'RepopackConfigMerged' from 'configSchema.js'
echo -e "\nSearching for imports from configSchema.js:"
rg "import.*\{.*RepopackConfigMerged.*\}.*from.*['\"].*configSchema\.js['\"]" --type-add 'ts:*.{ts,js}'

Length of output: 1637


Script:

#!/bin/bash

# Check if 'src/config/configSchema.ts' exists
echo "Checking for src/config/configSchema.ts:"
if [ -f src/config/configSchema.ts ]; then
    echo "File exists"
    
    # Check if 'RepopackConfigMerged' is exported from 'configSchema.ts'
    echo -e "\nChecking exports in configSchema.ts:"
    rg "export.*type.*RepopackConfigMerged" src/config/configSchema.ts
else
    echo "File does not exist"
fi

Length of output: 400

src/shared/errorHandler.ts (2)

1-1: Importing Zod library for schema validation

The import statement correctly brings in the Zod library, enabling robust configuration validation.


11-16: Addition of custom error class for configuration validation

The RepopackConfigValidationError class appropriately extends RepopackError and sets the error name for precise error identification.

src/core/file/fileProcessor.ts (1)

2-2: Ensure all references to configTypes.js are updated

To maintain consistency and prevent potential type mismatches, please verify that all imports from '../../config/configTypes.js' have been updated to '../../config/configSchema.js' throughout the codebase.

Run the following script to identify any remaining references to configTypes.js:

Verification successful

To ensure a thorough verification, I'll generate additional shell scripts to search for related terms. This will help us confirm whether all references have been updated correctly.

These scripts will help us get a clearer picture of the current state of the codebase regarding the use of 'configTypes' and 'configSchema'.


All references to configTypes.js have been successfully updated

The verification process has confirmed that all references to 'configTypes.js' have been correctly updated to 'configSchema.js' throughout the codebase. No remaining instances of 'configTypes.js' were found, and 'configSchema.js' is being consistently used across various files.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all files importing from 'configTypes.js'
# Test: Search for imports from 'configTypes.js'. Expectation: No matches found.

rg --type js --type ts --no-heading 'from\s+.*configTypes\.js'

Length of output: 64


Script:

#!/bin/bash
# Search for any remaining references to 'configTypes'
echo "Searching for 'configTypes':"
rg --type js --type ts --no-heading 'configTypes'

# Search for usage of 'configSchema'
echo "Searching for 'configSchema':"
rg --type js --type ts --no-heading 'configSchema'

# Broader search for 'config' and 'Types' to catch potential partial matches
echo "Searching for 'config' and 'Types':"
rg --type js --type ts --no-heading 'config.*Types'

Length of output: 2093

src/core/output/outputGenerator.ts (1)

3-3: Import update aligns with Zod integration for configuration validation

The import statement now correctly imports RepopackConfigMerged from configSchema.js, reflecting the shift to using Zod schemas for robust configuration validation. This change ensures that the type definitions are consistent with the new schema-based validation approach.

src/core/output/outputStyleDecorator.ts (1)

1-1: Verify that 'RepopackConfigMerged' is correctly exported from 'configSchema.js'

The import statement has been updated to import RepopackConfigMerged from '../../config/configSchema.js' instead of '../../config/configTypes.js'. Please ensure that RepopackConfigMerged is indeed exported from configSchema.js and that this change is consistent throughout the codebase.

Run the following script to confirm that RepopackConfigMerged is exported from configSchema.js:

Verification successful

'RepopackConfigMerged' is correctly exported from the config schema file

The verification confirms that 'RepopackConfigMerged' is indeed exported from 'src/config/configSchema.ts'. The import statement in 'outputStyleDecorator.ts' correctly references this export, although there's a minor difference in file extension ('.js' vs '.ts') which is typical in TypeScript projects.

  • The export is found in 'src/config/configSchema.ts', line 79:
    export type RepopackConfigMerged = z.infer<typeof repopackConfigMergedSchema>;
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that 'RepopackConfigMerged' is exported from 'configSchema.js'

# Test: Search for the export of 'RepopackConfigMerged' in the codebase.
# Expectation: The export should be located in 'configSchema.js'.

ast-grep --lang typescript --pattern 'export type RepopackConfigMerged = $_'

# Note: This will list all files where 'RepopackConfigMerged' is exported. Ensure it points to 'configSchema.js'.

Length of output: 187

package.json (1)

66-67: Addition of zod dependency is appropriate

Including zod in your dependencies supports your goal of enhancing configuration validation.

src/core/security/securityCheckRunner.ts (1)

5-5: Verify that picocolors is included in the project dependencies

Please ensure that picocolors is added to your project's dependencies to prevent runtime errors.

Run the following script to check if picocolors is listed in package.json:

Verification successful

'picocolors' is correctly included in the project dependencies

The verification process confirms that 'picocolors' is properly listed in the project's dependencies in package.json with version "^1.1.0". This ensures that the package will be installed when setting up the project, preventing potential runtime errors related to missing dependencies.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that 'picocolors' is listed in package.json dependencies or devDependencies.

# Test: Check for 'picocolors' in 'package.json'.
# Expect: 'picocolors' should be listed under dependencies or devDependencies.

jq '.dependencies.picocolors, .devDependencies.picocolors' package.json

Length of output: 87

src/core/file/fileSearcher.ts (1)

2-2: Verify the export of 'RepopackConfigMerged' from 'configSchema.js'

The import path for RepopackConfigMerged has been updated to '../../config/configSchema.js'. Ensure that RepopackConfigMerged is correctly exported from configSchema.js and that it matches the expected type definitions.

Run the following script to verify the export:

Verification successful

To gather more information and address the remaining concerns, I'll run additional scripts to inspect the import statement and the schema definition.


RepopackConfigMerged export verified successfully

The export of 'RepopackConfigMerged' from 'configSchema.js' has been verified. The type is correctly defined and exported, and its usage is consistent with the project's conventions. The import statement in 'fileSearcher.ts' is also correct.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that 'RepopackConfigMerged' is exported from 'configSchema.js'

# Test: Search for the export statement of 'RepopackConfigMerged' in 'configSchema.js'
# Expect: An export of 'RepopackConfigMerged' type definition.
ast-grep --lang typescript --pattern $'export type RepopackConfigMerged = $_' ./src/config/configSchema.ts

Length of output: 216


Script:

#!/bin/bash
# Description: Verify the import statement and schema definition

# Test 1: Check the import statement in fileSearcher.ts
echo "Checking import statement:"
rg "import.*RepopackConfigMerged" src/core/file/fileSearcher.ts

# Test 2: Inspect the definition of repopackConfigMergedSchema
echo -e "\nChecking repopackConfigMergedSchema definition:"
ast-grep --lang typescript --pattern 'const repopackConfigMergedSchema = $_' src/config/configSchema.ts

# Test 3: Check for other usages of z.infer in the project
echo -e "\nChecking other usages of z.infer:"
rg "z\.infer" --type ts

Length of output: 1482

tests/integration-tests/packager.test.ts (1)

7-7: Updated import statement to reflect reorganization

The import statement now references types from configSchema.js instead of configTypes.js, aligning with the integration of Zod for configuration validation. Ensure that configSchema.js exports RepopackConfigFile, RepopackConfigMerged, and RepopackOutputStyle as expected.

Run the following script to confirm that the required types are exported:

Verification successful

Import statement is correct and types are properly exported

The import statement in tests/integration-tests/packager.test.ts correctly references the required types from ../../src/config/configSchema.js. Although the actual definitions are in TypeScript files, the .js extension in the import is correct due to TypeScript's module resolution:

  • RepopackConfigFile, RepopackConfigMerged, and RepopackOutputStyle are exported in src/config/configSchema.ts
  • RepopackConfigFile is also re-exported as RepopackConfig in src/index.ts

The review comment's suggestion to update the import statement was accurate, aligning with the integration of Zod for configuration validation.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that 'configSchema.js' exports the required types.

# Expected: The types 'RepopackConfigFile', 'RepopackConfigMerged', and 'RepopackOutputStyle' are exported.

# Command:
rg --type js 'export type.*(RepopackConfigFile|RepopackConfigMerged|RepopackOutputStyle)' -g 'configSchema.js'

Length of output: 259


Script:

#!/bin/bash
# Search for configSchema.js file
echo "Searching for configSchema.js:"
fd configSchema.js

# If found, display its contents
if [ $? -eq 0 ]; then
    echo -e "\nContents of configSchema.js:"
    cat $(fd configSchema.js)
else
    echo -e "\nconfigSchema.js not found. Searching for files with the required type definitions:"
    rg --type ts 'export type.*(RepopackConfigFile|RepopackConfigMerged|RepopackOutputStyle)'
fi

Length of output: 210


Script:

#!/bin/bash
# Display contents of configSchema.js
echo "Contents of configSchema.js:"
cat $(fd configSchema.js)

# If file is empty or doesn't contain expected exports, search for TypeScript files
if [ ! -s "$(fd configSchema.js)" ] || ! grep -q "export type" "$(fd configSchema.js)"; then
    echo -e "\nSearching for TypeScript files with the required type definitions:"
    rg --type ts 'export type.*(RepopackConfigFile|RepopackConfigMerged|RepopackOutputStyle)'
fi

# Check the import statement in the original file
echo -e "\nChecking import statement in tests/integration-tests/packager.test.ts:"
rg "import type.*from '../../src/config/configSchema" tests/integration-tests/packager.test.ts

Length of output: 1164

src/cli/cliRunner.ts (1)

4-4: LGTM!

The import statement for RepopackOutputStyle has been correctly updated to reflect the new configuration schema.

src/cli/cliPrinter.ts (1)

3-3: Updated import to reflect configuration schema changes

The import statement has been updated to import RepopackConfigMerged from ../config/configSchema.js instead of ../config/configTypes.js. This change aligns with the integration of Zod for configuration validation and suggests that types are now defined in configSchema.js.

Run the following script to ensure there are no remaining imports from configTypes.js in the codebase:

Verification successful

To ensure we have accurate information about the remaining imports, I'll generate new shell scripts to verify the ripgrep functionality and use an alternative search method.


Import change successfully implemented

The verification process confirms that there are no remaining imports from '../config/configTypes.js' in the codebase. The change to import RepopackConfigMerged from '../config/configSchema.js' has been consistently applied, aligning with the integration of Zod for configuration validation.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining imports from '../config/configTypes.js'

# Expected Result: No occurrences of imports from '../config/configTypes.js'

rg "from ['\"]\.\./config/configTypes\.js['\"]"

Length of output: 53


Script:

#!/bin/bash

# Test ripgrep functionality with a simple pattern
echo "Testing ripgrep functionality:"
rg "import"

# Use fd to find all TypeScript and JavaScript files, then use grep to search for the import
echo "Searching for '../config/configTypes.js' imports:"
fd -e ts -e js -x grep -n "from ['\"]../config/configTypes.js['\"]" {}

Length of output: 23042

src/cli/actions/defaultActionRunner.ts (2)

3-11: Imports Updated for Configuration Validation

The added imports for RepopackConfig types, repopackConfigCliSchema, and rethrowValidationErrorIfZodError correctly support the new configuration validation using Zod. This enhances type safety and validation throughout the module.


34-34: Extraction of CLI Config Parsing into buildCliConfig Function

Refactoring the CLI options parsing into the buildCliConfig function improves code readability and maintains separation of concerns. This makes the runDefaultAction function cleaner and easier to maintain.

src/core/packager.ts (3)

5-5: Correct import of 'RepopackConfigMerged' type

The import of the type RepopackConfigMerged from '../config/configSchema.js' is appropriate and follows TypeScript best practices.


97-97: Enhanced progress logging with file path formatting

Including the file path in the progress callback enhances logging clarity, allowing users to see which file is being processed. Using pc.dim(file.path) to dim the file path improves readability in the console output.


4-4: Ensure 'picocolors' is added to project dependencies

The module 'picocolors' is being imported, but there's no indication that it has been added to the project's dependencies. Please ensure that 'picocolors' is listed in your package.json file under dependencies to prevent import errors.

Run the following script to verify if 'picocolors' is included in package.json dependencies:

Verification successful

'picocolors' is correctly listed in project dependencies

The verification process confirms that 'picocolors' is properly included in the project's dependencies. The package.json file lists 'picocolors' with the version "^1.1.0", which allows for compatible updates within the 1.x.x range. No further action is required regarding this dependency.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that 'picocolors' is listed in the project's package.json dependencies.

# Test: Check if 'picocolors' is in the dependencies. Expect: 'picocolors' should be listed under 'dependencies' or 'devDependencies'.

jq '.dependencies.picocolors // .devDependencies.picocolors' package.json

Length of output: 84

tests/config/configLoader.test.ts (5)

7-7: Import statements for new types and error classes are correctly added

The imports for RepopackConfigCli, RepopackConfigFile, and RepopackConfigValidationError are appropriate and necessary for the updated test cases.

Also applies to: 9-9


32-34: Mock configuration in test is properly structured

The mock configuration for the test 'should load and parse a valid local config file' is accurately defined with valid types for filePath, style, and useDefaultPatterns.


42-51: Test correctly validates handling of invalid configuration

The test 'should throw RepopackConfigValidationError for invalid config' effectively checks that the loadFileConfig function throws an error when provided with an invalid configuration. This ensures robust validation and error handling.


55-57: Global configuration mock includes additional 'style' property

Including the style property in the global configuration enhances test coverage by verifying that global configurations are loaded with all relevant properties.


91-102: Test verifies correct merging of file and CLI configurations

The test 'should correctly merge configs' appropriately checks that CLI configurations override file configurations and that properties from both sources are merged as expected.

src/cli/actions/initActionRunner.ts (1)

5-5: Import update reflects integration of Zod for configuration validation

The import statement now references configSchema.js instead of configTypes.js, aligning with the introduction of Zod for robust configuration validation as stated in the PR objectives. This change ensures that the configuration types are correctly imported from the updated schema, enhancing type safety and validation throughout the application.

Comment on lines +31 to +38
export const rethrowValidationErrorIfZodError = (error: unknown, message: string): void => {
if (error instanceof z.ZodError) {
const zodErrorText = error.errors.map((err) => `${err.path.join('.')}: ${err.message}`).join(', ');
throw new RepopackConfigValidationError(
`${message}\n ${zodErrorText}\n Please check the config file and try again.`,
);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding unit tests for the new validation error handling

The rethrowValidationErrorIfZodError function enhances error handling by wrapping Zod validation errors into a custom error class. To ensure its reliability and to catch potential edge cases, consider adding unit tests that cover various validation failure scenarios.

Would you like assistance in creating unit tests for this function, or should I open a GitHub issue to track this task?

package.json Show resolved Hide resolved
@@ -31,7 +32,7 @@ export const runSecurityCheck = async (
};
}

progressCallback(`Running security check... (${index + 1}/${rawFiles.length})`);
progressCallback(`Running security check... (${index + 1}/${rawFiles.length}) ${pc.dim(rawFile.path)}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure progressCallback is called regardless of security issues

Currently, the progressCallback is only invoked when no security issues are found in the file. This may lead to inaccurate progress reporting. Consider moving the progressCallback call before the condition to ensure it runs for every file processed.

Apply this diff to move the progressCallback call:

         const secretLintResult = await runSecretLint(rawFile.path, rawFile.content, secretLintConfig);

+        progressCallback(`Running security check... (${index + 1}/${rawFiles.length}) ${pc.dim(rawFile.path)}`);

         if (secretLintResult.messages.length > 0) {
             return {
                 filePath: rawFile.path,
                 messages: secretLintResult.messages.map((message) => message.message),
             };
         }

-        progressCallback(`Running security check... (${index + 1}/${rawFiles.length}) ${pc.dim(rawFile.path)}`);

         // Sleep for a short time to prevent blocking the event loop
         await sleep(1);
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
progressCallback(`Running security check... (${index + 1}/${rawFiles.length}) ${pc.dim(rawFile.path)}`);
const secretLintResult = await runSecretLint(rawFile.path, rawFile.content, secretLintConfig);
progressCallback(`Running security check... (${index + 1}/${rawFiles.length}) ${pc.dim(rawFile.path)}`);
if (secretLintResult.messages.length > 0) {
return {
filePath: rawFile.path,
messages: secretLintResult.messages.map((message) => message.message),
};
}
// Sleep for a short time to prevent blocking the event loop
await sleep(1);


export type RepopackOutputStyle = z.infer<typeof repopackOutputStyleSchema>;

const repopackConfigBaseSchema = z.object({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Export repopackConfigBaseSchema for Consistency and Reusability

Since repopackConfigBaseSchema serves as the foundation for other schemas and might be useful in other modules or for further extensions, consider exporting it to promote reusability and maintain consistency.

Apply this diff to export the base schema:

-const repopackConfigBaseSchema = z.object({
+export const repopackConfigBaseSchema = z.object({
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const repopackConfigBaseSchema = z.object({
export const repopackConfigBaseSchema = z.object({

Comment on lines +36 to +38
export const repopackConfigDefaultSchema = repopackConfigBaseSchema.and(
z.object({
output: z.object({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use .extend() Instead of .and() for Object Schema Extension

When extending an object schema, it's more appropriate to use .extend() rather than .and(). The .extend() method is specifically designed for adding new fields to an existing schema and ensures better handling of overlapping keys.

Apply this diff to replace .and() with .extend():

-export const repopackConfigDefaultSchema = repopackConfigBaseSchema.and(
+export const repopackConfigDefaultSchema = repopackConfigBaseSchema.extend(
  z.object({
    output: z.object({
      filePath: z.string(),
      style: repopackOutputStyleSchema,
      headerText: z.string().optional(),
      instructionFilePath: z.string().optional(),
      removeComments: z.boolean(),
      removeEmptyLines: z.boolean(),
      topFilesLength: z.number(),
      showLineNumbers: z.boolean(),
    }),
    include: z.array(z.string()),
    ignore: z.object({
      useGitignore: z.boolean(),
      useDefaultPatterns: z.boolean(),
      customPatterns: z.array(z.string()).optional(),
    }),
    security: z.object({
      enableSecurityCheck: z.boolean(),
    }),
  }),
);
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const repopackConfigDefaultSchema = repopackConfigBaseSchema.and(
z.object({
output: z.object({
export const repopackConfigDefaultSchema = repopackConfigBaseSchema.extend(
z.object({
output: z.object({

Comment on lines +3 to +4
import { z } from 'zod';
import { RepopackError, rethrowValidationErrorIfZodError } from '../shared/errorHandler.js';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import: 'z' from 'zod'

The imported z from 'zod' is not directly used in this file. Since the schema parsing is handled through imported schemas (repopackConfigFileSchema and repopackConfigMergedSchema), the direct import of z may not be necessary.

Consider removing the unused import to keep the code clean:

-import { z } from 'zod';
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { z } from 'zod';
import { RepopackError, rethrowValidationErrorIfZodError } from '../shared/errorHandler.js';
import { RepopackError, rethrowValidationErrorIfZodError } from '../shared/errorHandler.js';

Comment on lines +112 to +115
return repopackConfigMergedSchema.parse(mergedConfig);
} catch (error) {
rethrowValidationErrorIfZodError(error, 'Invalid merged config');
throw error;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove redundant error rethrow in merged configuration validation

After calling rethrowValidationErrorIfZodError(error, 'Invalid merged config');, the subsequent throw error; may be unnecessary if the function already throws the error. This redundancy could lead to confusion about which error is ultimately thrown.

Apply this diff to eliminate the redundant throw statement:

} catch (error) {
  rethrowValidationErrorIfZodError(error, 'Invalid merged config');
- throw error;
}

This change ensures that the error handling is clear and that only the intended error is propagated.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return repopackConfigMergedSchema.parse(mergedConfig);
} catch (error) {
rethrowValidationErrorIfZodError(error, 'Invalid merged config');
throw error;
return repopackConfigMergedSchema.parse(mergedConfig);
} catch (error) {
rethrowValidationErrorIfZodError(error, 'Invalid merged config');
}

Comment on lines +68 to +70
return repopackConfigFileSchema.parse(config);
} catch (error) {
if (error instanceof RepopackConfigValidationError) {
throw new RepopackError(`Invalid configuration in ${filePath}: ${error.message}`);
}
rethrowValidationErrorIfZodError(error, 'Invalid config schema');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistent error handling in configuration parsing

When parsing the configuration file with repopackConfigFileSchema.parse(config), any validation errors thrown by Zod are handled by rethrowValidationErrorIfZodError(error, 'Invalid config schema');. If this function rethrows the error, the subsequent error handling code might be unreachable. To avoid redundancy and potential confusion, consider simplifying the error handling to ensure that errors are handled appropriately without overlapping.

Apply this diff to streamline the error handling:

} catch (error) {
  rethrowValidationErrorIfZodError(error, 'Invalid config schema');
- if (error instanceof SyntaxError) {
-   throw new RepopackError(`Invalid JSON in config file ${filePath}: ${error.message}`);
- }
- if (error instanceof Error) {
-   throw new RepopackError(`Error loading config from ${filePath}: ${error.message}`);
- }
- throw new RepopackError(`Error loading config from ${filePath}`);
}

Ensure that rethrowValidationErrorIfZodError handles all necessary error cases, including JSON parsing errors.

Committable suggestion was skipped due to low confidence.

Comment on lines +85 to +110
): RepopackConfigMerged => {
const mergedConfig = {
cwd,
output: {
...defaultConfig.output,
...fileConfig.output,
...cliConfig.output,
},
ignore: {
...defaultConfig.ignore,
...fileConfig.ignore,
...cliConfig.ignore,
customPatterns: [
...(defaultConfig.ignore.customPatterns || []),
...(fileConfig.ignore?.customPatterns || []),
...(cliConfig.ignore?.customPatterns || []),
],
},
include: [...(defaultConfig.include || []), ...(fileConfig.include || []), ...(cliConfig.include || [])],
security: {
...defaultConfig.security,
...fileConfig.security,
...cliConfig.security,
},
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider deep merging for nested configuration objects

When merging configurations, properties like output, ignore, and security are being shallowly merged. If these properties contain nested objects or arrays, a shallow merge might not combine them as expected, potentially overwriting entire sections of the configuration.

To ensure all nested properties are correctly merged, consider using a deep merge utility like lodash.merge. Here's how you might implement it:

+ import merge from 'lodash.merge';

...

export const mergeConfigs = (
  cwd: string,
  fileConfig: RepopackConfigFile,
  cliConfig: RepopackConfigCli,
): RepopackConfigMerged => {
- const mergedConfig = {
-   cwd,
-   output: {
-     ...defaultConfig.output,
-     ...fileConfig.output,
-     ...cliConfig.output,
-   },
-   ignore: {
-     ...defaultConfig.ignore,
-     ...fileConfig.ignore,
-     ...cliConfig.ignore,
-     customPatterns: [
-       ...(defaultConfig.ignore.customPatterns || []),
-       ...(fileConfig.ignore?.customPatterns || []),
-       ...(cliConfig.ignore?.customPatterns || []),
-     ],
-   },
-   include: [...(defaultConfig.include || []), ...(fileConfig.include || []), ...(cliConfig.include || [])],
-   security: {
-     ...defaultConfig.security,
-     ...fileConfig.security,
-     ...cliConfig.security,
-   },
- };
+ const mergedConfig = merge({}, defaultConfig, fileConfig, cliConfig, { cwd });

  try {
    return repopackConfigMergedSchema.parse(mergedConfig);
  } catch (error) {
    rethrowValidationErrorIfZodError(error, 'Invalid merged config');
    throw error;
  }
};

This approach provides a more robust merging strategy, ensuring that all configuration values are appropriately combined without unintended overwrites.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
): RepopackConfigMerged => {
const mergedConfig = {
cwd,
output: {
...defaultConfig.output,
...fileConfig.output,
...cliConfig.output,
},
ignore: {
...defaultConfig.ignore,
...fileConfig.ignore,
...cliConfig.ignore,
customPatterns: [
...(defaultConfig.ignore.customPatterns || []),
...(fileConfig.ignore?.customPatterns || []),
...(cliConfig.ignore?.customPatterns || []),
],
},
include: [...(defaultConfig.include || []), ...(fileConfig.include || []), ...(cliConfig.include || [])],
security: {
...defaultConfig.security,
...fileConfig.security,
...cliConfig.security,
},
};
): RepopackConfigMerged => {
const mergedConfig = merge({}, defaultConfig, fileConfig, cliConfig, { cwd });
try {
return repopackConfigMergedSchema.parse(mergedConfig);
} catch (error) {
rethrowValidationErrorIfZodError(error, 'Invalid merged config');
throw error;
}
};

Comment on lines +108 to +118
test('should throw RepopackConfigValidationError for invalid merged config', () => {
const fileConfig: RepopackConfigFile = {
output: { filePath: 'file-output.txt', style: 'plain' },
};
const cliConfig: RepopackConfigCli = {
// @ts-ignore
output: { style: 'invalid' }, // Invalid style
};

expect(() => mergeConfigs(process.cwd(), fileConfig, cliConfig)).toThrow(RepopackConfigValidationError);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using '@ts-ignore'; use explicit type casting instead

Using @ts-ignore suppresses TypeScript's type checking and may mask other issues. For better type safety, consider casting the invalid configuration to unknown and then to RepopackConfigCli.

Apply this change to improve type safety:

-   const cliConfig: RepopackConfigCli = {
-     // @ts-ignore
      output: { style: 'invalid' }, // Invalid style
-   };
+   const cliConfig = {
+     output: { style: 'invalid' }, // Invalid style
+   } as unknown as RepopackConfigCli;
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('should throw RepopackConfigValidationError for invalid merged config', () => {
const fileConfig: RepopackConfigFile = {
output: { filePath: 'file-output.txt', style: 'plain' },
};
const cliConfig: RepopackConfigCli = {
// @ts-ignore
output: { style: 'invalid' }, // Invalid style
};
expect(() => mergeConfigs(process.cwd(), fileConfig, cliConfig)).toThrow(RepopackConfigValidationError);
});
test('should throw RepopackConfigValidationError for invalid merged config', () => {
const fileConfig: RepopackConfigFile = {
output: { filePath: 'file-output.txt', style: 'plain' },
};
const cliConfig = {
output: { style: 'invalid' }, // Invalid style
} as unknown as RepopackConfigCli;
expect(() => mergeConfigs(process.cwd(), fileConfig, cliConfig)).toThrow(RepopackConfigValidationError);
});

@yamadashy yamadashy closed this Sep 23, 2024
@yamadashy yamadashy deleted the feature/more-message branch September 23, 2024 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant