Skip to content

Conversation

@stepan662
Copy link
Contributor

@stepan662 stepan662 commented Jan 22, 2025

Based on #140
Closes #137

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added support for specifying namespaces to synchronize via configuration and CLI options.
    • Introduced a CLI option to filter synchronization by namespaces.
  • Bug Fixes

    • Improved handling of keys without a namespace by consistently treating them as empty strings.
  • Tests

    • Added and updated end-to-end tests for namespace-specific synchronization and push functionality.
    • Enhanced test coverage for conflict handling and selective language/namespace operations.
    • Improved test utilities for safer data handling and flexible file configuration.
  • Chores

    • Removed and refactored obsolete test files to streamline the test suite.

@stepan662 stepan662 force-pushed the stepangranat/sync-namespaces branch from 2c9cc42 to 120782c Compare June 5, 2025 10:21
@coderabbitai
Copy link

coderabbitai bot commented Jun 5, 2025

Walkthrough

This update introduces namespace filtering to the synchronization and push commands, allowing operations to be limited to specified namespaces. The schema, CLI, and internal logic are updated to support this feature. Additionally, the representation of the default namespace is unified as an empty string. Comprehensive end-to-end tests are refactored and expanded to cover these changes.

Changes

File(s) Change Summary
schema.json, src/schema.d.ts Added optional namespaces property to the sync object for namespace filtering.
src/commands/sync/sync.ts Added support for namespaces option in sync command and CLI, filtering keys by namespace.
src/commands/sync/syncUtils.ts, src/extractor/runner.ts Replaced NullNamespace symbol with '' (empty string) for default namespace handling.
test/e2e/push.p1.test.ts, test/e2e/push.p2.test.ts, test/e2e/push.p3.test.ts Added new, modular end-to-end test suites for push command with varied scenarios and configurations.
test/e2e/push.test.ts Deleted the old monolithic push command end-to-end test suite.
test/e2e/sync.test.ts Extended sync tests to cover namespace filtering and selective deletion.
test/e2e/compare.test.ts Updated expected unused key count and assertions for Project 3.
test/fixtures/testProjectCode/Test3Mixed.tsx Modified translation components and namespaces in test fixture.
test/e2e/utils/data.ts Improved safety when accessing nested keys in utility function.
test/e2e/utils/pushFilesConfig.ts Added utility to generate file match configs for push command tests.

Sequence Diagram(s)

sequenceDiagram
    participant CLI_User
    participant CLI
    participant SyncLogic
    participant TolgeeAPI

    CLI_User->>CLI: Run sync/push command with --namespaces option
    CLI->>SyncLogic: Pass namespaces option
    SyncLogic->>SyncLogic: Filter local and remote keys by namespaces
    SyncLogic->>TolgeeAPI: Fetch or update keys (filtered by namespace)
    TolgeeAPI-->>SyncLogic: Respond with filtered key data
    SyncLogic->>CLI: Output results (added/removed keys)
    CLI->>CLI_User: Display sync/push summary
Loading

Suggested labels

released

Poem

A bunny hopped through fields of code,
Filtering namespaces, lightening the load.
Push and sync now know their place—
Only chosen keys join the race!
With tests anew and logic neat,
This update makes our project sweet.
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-05T12_30_35_882Z-debug-0.log


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd4246c and c2c7ec5.

📒 Files selected for processing (2)
  • schema.json (1 hunks)
  • src/commands/sync/sync.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/commands/sync/sync.ts
  • schema.json
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: E2E Tests (ubuntu-latest, 20)
  • GitHub Check: Unit Tests (windows-latest, 22)
  • GitHub Check: E2E Tests (ubuntu-latest, 22)
  • GitHub Check: E2E Tests (ubuntu-latest, 18)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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.

@stepan662 stepan662 marked this pull request as ready for review June 5, 2025 10:23
Copy link

@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: 1

🧹 Nitpick comments (2)
test/e2e/utils/pushFilesConfig.ts (1)

4-19: Consider adding input validation for security.

The utility function is well-designed and follows clear patterns. However, consider adding validation for the namespaces parameter to prevent potential path traversal attacks, as namespace values are used directly in URL construction.

 export function pushFilesConfig(base: URL, namespaces: string[] = ['']) {
+  // Validate namespaces to prevent path traversal
+  const sanitizedNamespaces = namespaces.map(ns => {
+    if (ns.includes('..') || ns.includes('/') || ns.includes('\\')) {
+      throw new Error(`Invalid namespace: ${ns}. Namespaces cannot contain path separators or traversal sequences.`);
+    }
+    return ns;
+  });
+  
   const result: FileMatch[] = [];
-  for (const ns of namespaces) {
+  for (const ns of sanitizedNamespaces) {
     result.push({

Alternatively, you could use a simple regex validation: /^[a-zA-Z0-9_-]*$/.test(ns) if namespaces should only contain alphanumeric characters, underscores, and hyphens.

test/e2e/sync.test.ts (1)

1-480: Suggest consolidating duplicate test patterns

While the test coverage is excellent, there's significant code duplication across the push test files (p1, p2, p3) in setup, teardown, and assertion patterns. Consider extracting common test utilities to reduce duplication and improve maintainability.

For example, you could create a shared utility for:

  • Common setup/teardown patterns
  • Standard API assertion helpers
  • Reusable test data validation functions

This would make the tests more maintainable while preserving their comprehensive coverage.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75eb346 and 120782c.

📒 Files selected for processing (14)
  • schema.json (1 hunks)
  • src/commands/sync/sync.ts (4 hunks)
  • src/commands/sync/syncUtils.ts (2 hunks)
  • src/extractor/runner.ts (1 hunks)
  • src/schema.d.ts (1 hunks)
  • test/__fixtures__/testProjectCode/Test3Mixed.tsx (0 hunks)
  • test/e2e/compare.test.ts (1 hunks)
  • test/e2e/push.p1.test.ts (1 hunks)
  • test/e2e/push.p2.test.ts (1 hunks)
  • test/e2e/push.p3.test.ts (1 hunks)
  • test/e2e/push.test.ts (0 hunks)
  • test/e2e/sync.test.ts (6 hunks)
  • test/e2e/utils/data.ts (1 hunks)
  • test/e2e/utils/pushFilesConfig.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • test/fixtures/testProjectCode/Test3Mixed.tsx
  • test/e2e/push.test.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
test/e2e/utils/pushFilesConfig.ts (1)
src/schema.d.ts (1)
  • FileMatch (236-245)
src/commands/sync/sync.ts (1)
src/commands/sync/syncUtils.ts (1)
  • compareKeys (49-101)
🔇 Additional comments (23)
schema.json (1)

170-177: LGTM! Schema definition follows established patterns.

The new namespaces property for the sync object is well-defined and consistent with similar properties in the push and pull objects. The optional array of strings type and descriptive text are appropriate.

src/schema.d.ts (1)

196-199: LGTM! TypeScript interface correctly reflects the schema.

The auto-generated TypeScript interface properly defines the optional namespaces property as string[] with appropriate documentation matching the JSON schema.

test/e2e/compare.test.ts (1)

177-179:

✅ Verification successful

Verify the updated test expectations are correct.

The test now expects 4 unused keys instead of 3 and includes a specific assertion for "onions (namespace: food)". Please ensure these updated expectations accurately reflect the new namespace filtering behavior.


🏁 Script executed:

#!/bin/bash
# Description: Verify the test fixture and understand the namespace changes
# Expected: Find the test fixture file and see what keys are actually present

# Look for the Test3Mixed.tsx fixture file
fd "Test3Mixed.tsx" --type f

# Show the content to understand what keys are being extracted
cat test/__fixtures__/testProjectCode/Test3Mixed.tsx

# Look for any other related test files that might give context
rg -A 5 -B 5 "onions.*food" test/

Length of output: 2858


🏁 Script executed:

#!/bin/bash
# Print relevant snippet from the compare test
echo "=== compare.test.ts (lines 150-200) ==="
sed -n '150,200p' test/e2e/compare.test.ts

# Locate translation.json in the test fixtures
echo
echo "=== translation.json files in fixtures ==="
fd translation.json --type f test/__fixtures__/testProjectCode

# Display the contents of each translation.json
for file in $(fd translation.json --type f test/__fixtures__/testProjectCode); do
  echo
  echo "=== Content of $file ==="
  cat "$file"
done

Length of output: 1448


🏁 Script executed:

#!/bin/bash
# Locate PROJECT_3 constant in the compare test
grep -R "PROJECT_3" -n test/e2e/compare.test.ts

# List all files in the fixtures directory
echo
echo "=== All fixtures under test/__fixtures__ ==="
find test/__fixtures__ -type f

# Specifically list JSON files to find translation data
echo
echo "=== JSON files in fixtures ==="
find test/__fixtures__ -type f -name "*.json"

Length of output: 9467


🏁 Script executed:

#!/bin/bash
# Find and display the contents of project3.js to inspect initial keys
files=$(fd project3.js --type f test)
for file in $files; do
  echo "=== Content of $file ==="
  sed -n '1,200p' "$file"
done

Length of output: 40


🏁 Script executed:

#!/bin/bash
# 1. Locate the project3 fixture file in the repository
echo "=== Searching for project3.js ==="
find . -type f | grep -i "project3.js\?$"

# 2. If found, display its contents to inspect the initial keys loaded
PROJECT3_PATH=$(find . -type f | grep -i "project3.js\?$" | head -n1)
if [ -n "$PROJECT3_PATH" ]; then
  echo
  echo "=== Content of $PROJECT3_PATH ==="
  sed -n '1,200p' "$PROJECT3_PATH"
else
  echo "project3.js not found in repository."
fi

# 3. Search for any .ts variant just in case
echo
echo "=== Searching for project3.ts ==="
find . -type f | grep -i "project3.ts\?$"

Length of output: 456


🏁 Script executed:

#!/bin/bash
# Display the contents of project3.ts to inspect initial translation keys and settings
echo "=== project3.ts ==="
sed -n '1,200p' test/e2e/utils/api/project3.ts

Length of output: 1898


🏁 Script executed:

#!/bin/bash
# Display translation keys for Project 3 fixtures
echo "=== test3/en.json ==="
cat test/__fixtures__/tolgeeImportData/test3/en.json || echo "File not found"

echo
echo "=== test3/drinks/en.json ==="
cat test/__fixtures__/tolgeeImportData/test3/drinks/en.json || echo "File not found"

echo
echo "=== test3/food/en.json ==="
cat test/__fixtures__/tolgeeImportData/test3/food/en.json || echo "File not found"

Length of output: 584


Test expectations for Project 3 compare() are correct

  • Translation import and code usage yield 4 new keys (welcome, table (ns furniture), chair (ns furniture), cookies (ns food)) and 4 unused keys (table, chair, soda (ns drinks), onions (ns food)).
  • The assertion for 4 unused keys and the specific check for - onions (namespace: food) accurately reflect the fixture data.
  • The other checks (+ cookies (namespace: food), - soda (namespace: drinks), + table (namespace: furniture), - table) also match the actual additions/removals.

No changes required.

src/extractor/runner.ts (1)

142-142: LGTM: Consistent namespace representation standardization.

The change from NullNamespace symbol to empty string '' for the default namespace is part of a consistent refactoring across the codebase. This standardization improves code maintainability and aligns with the new namespace filtering functionality.

test/e2e/utils/data.ts (1)

3-3: LGTM: Improved error handling with defensive programming.

The addition of optional chaining and nullish coalescing (data._embedded?.keys ?? []) prevents runtime errors when the API response structure is incomplete. This defensive approach improves test reliability by gracefully handling missing or undefined nested properties.

src/commands/sync/syncUtils.ts (3)

57-57: LGTM: Consistent namespace standardization in key comparison.

The changes to use empty string '' instead of NullNamespace for keys without namespaces are consistent with the overall refactoring. This standardization ensures uniform namespace representation throughout the comparison logic.

Also applies to: 63-63


69-69: LGTM: Simplified namespace iteration.

Removing the special handling of NullNamespace and using standard object key iteration is cleaner and more intuitive. The empty string namespace is now treated like any other namespace key.


77-77: LGTM: Consistent namespace fallback in added keys.

The change to use empty string '' as the namespace fallback maintains consistency with the overall refactoring pattern and ensures proper namespace representation for keys being added.

src/commands/sync/sync.ts (3)

27-27: LGTM: Proper type definition for namespaces option.

The addition of namespaces?: string[] to the Options type is correctly typed and follows TypeScript conventions for optional array properties.


85-91: LGTM: Correct local key filtering implementation.

The local key filtering logic correctly clears keys from namespaces not specified in the filter list. This approach efficiently removes unwanted keys before comparison while preserving the existing data structure.


243-248: LGTM: Well-defined CLI option for namespaces.

The CLI option definition is properly structured with clear description and correct default value resolution from configuration. The option accepts multiple namespace values as expected.

test/e2e/push.p2.test.ts (3)

1-29: LGTM: Well-structured test setup

The file imports, constants, and setup/teardown logic are well-organized and follow good testing practices with proper resource management.


30-66: LGTM: Proper conflict detection test

The test correctly verifies that push fails when conflicts exist (exit code 1) and validates that no changes are made to the remote data when conflicts are detected.


147-186: LGTM: Interactive confirmation test is well implemented

The test using runWithStdin with 'OVERRIDE' input properly simulates user interaction for conflict resolution. The assertion validates that the override actually took effect by checking the updated values.

test/e2e/push.p1.test.ts (3)

31-65: LGTM: Comprehensive basic push test

The test properly validates that all languages from the files are pushed when no filters are applied, and correctly verifies the stored translations via API calls.


67-99: LGTM: Language filtering validation

The test correctly validates that only the specified language ('fr') is pushed when using the -l flag, demonstrating proper language filtering functionality.


101-132: LGTM: Config-based language filtering

The test demonstrates that language filtering works consistently whether specified via CLI arguments or configuration file, using the pushFilesConfig utility appropriately.

test/e2e/push.p3.test.ts (3)

37-72: LGTM: Comprehensive namespace push test

The test properly validates that files with different namespace structures (default and 'drinks' namespace) are correctly pushed and stored with their respective namespace assignments.


74-106: LGTM: Namespace filtering functionality

The test correctly validates that only the specified namespace ('drinks') is pushed when using the -n flag, demonstrating proper namespace filtering.


232-284: Excellent test for namespace-scoped key removal

This test validates a critical edge case: when using --remove-other-keys with namespace filtering, only keys within the filtered namespaces should be considered for removal. Keys in other namespaces should remain untouched. The test correctly expects the 'knife' key to remain since it's outside the 'drinks' namespace filter.

test/e2e/sync.test.ts (3)

34-35: LGTM: Clear constant renaming

The renaming from CODE_PROJECT_3 to CODE_PROJECT_3_DIFF and addition of CODE_PROJECT_3_MIXED improves clarity about which test fixture is being used.


354-385: LGTM: Comprehensive namespace filtering test

The test properly validates that sync with --namespaces food only adds keys from the 'food' namespace while leaving other namespaces untouched. The assertion checking for 'table' (in food namespace) but not 'welcome' (in other namespace) is particularly good.


414-448: Critical test for namespace-scoped deletion

This test validates that --remove-unused with namespace filtering only deletes keys within the specified namespace ('food'), leaving keys in other namespaces intact. This is crucial for preventing accidental deletion of keys outside the scope of synchronization.

Copy link

@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: 0

🧹 Nitpick comments (1)
test/e2e/sync.test.ts (1)

387-396: Remove unused helper function.

The print() function is defined but never used, as flagged by ESLint.

-  async function print() {
-    const keys = await client.GET('/v2/projects/{projectId}/translations', {
-      params: {
-        path: { projectId: client.getProjectId() },
-      },
-    });
-
-    const stored = tolgeeDataToDict(keys.data);
-    console.log(stored);
-  }
🧰 Tools
🪛 GitHub Check: ESLint

[warning] 387-387:
'print' is defined but never used. Allowed unused vars must match /^_/u

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 120782c and d905ddd.

📒 Files selected for processing (4)
  • src/commands/sync/sync.ts (4 hunks)
  • test/__fixtures__/testProjectCode/Test3Mixed.tsx (2 hunks)
  • test/e2e/compare.test.ts (1 hunks)
  • test/e2e/sync.test.ts (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/e2e/compare.test.ts
  • src/commands/sync/sync.ts
  • test/fixtures/testProjectCode/Test3Mixed.tsx
🧰 Additional context used
🪛 GitHub Check: ESLint
test/e2e/sync.test.ts

[warning] 387-387:
'print' is defined but never used. Allowed unused vars must match /^_/u

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: E2E Tests (ubuntu-latest, 20)
  • GitHub Check: Unit Tests (windows-latest, 22)
  • GitHub Check: E2E Tests (ubuntu-latest, 18)
  • GitHub Check: E2E Tests (ubuntu-latest, 22)
🔇 Additional comments (6)
test/e2e/sync.test.ts (6)

34-35: LGTM: Constants renamed appropriately for new test fixtures.

The renaming from CODE_PROJECT_3 to CODE_PROJECT_3_DIFF and addition of CODE_PROJECT_3_MIXED aligns with the test fixture changes to support namespace testing scenarios.


300-300: LGTM: Existing tests updated to use renamed constant.

The existing namespace tests correctly use the renamed CODE_PROJECT_3_DIFF constant.

Also applies to: 329-329


354-385: LGTM: Comprehensive test for namespace filtering via CLI args.

This test effectively validates that the --namespaces flag filters synchronization to only the specified namespace ('food'), correctly adding 1 string and identifying unused keys outside the filtered namespace.


398-425: LGTM: Comprehensive test for namespace filtering via config.

This test validates namespace filtering through configuration files, correctly testing both default namespace ('') and 'food' namespace synchronization. The expected results (2 strings added, 6 unused keys) are consistent with the multi-namespace scenario.


427-466: LGTM: Excellent test for selective key deletion with namespace filtering.

This test comprehensively validates that --remove-unused respects namespace boundaries when using the --namespaces flag. The use of both --namespaces= (empty string for default namespace) and --namespaces=food demonstrates proper handling of multiple namespace specification.


468-497: LGTM: Config-based namespace deletion test validates key behavior.

This test confirms that namespace-scoped deletion works correctly through configuration files, properly removing only keys within the specified 'food' namespace while preserving keys in other namespaces.

@stepan662 stepan662 requested a review from JanCizmar June 5, 2025 12:24
@stepan662 stepan662 merged commit 4b9f46d into main Jun 11, 2025
15 checks passed
@stepan662 stepan662 deleted the stepangranat/sync-namespaces branch June 11, 2025 13:57
@github-actions
Copy link

🎉 This PR is included in version 2.13.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sync --remove-unused should respect push.namespaces

4 participants