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

Update to latest @dtdot/eslint-config #150

Merged
merged 4 commits into from
Dec 23, 2024

Conversation

danielemery
Copy link
Owner

@danielemery danielemery commented Dec 19, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a new caching mechanism with a Cache interface and a MemoryCache class for efficient data storage and retrieval.
    • Added a method to the AuthorisationService for role-based user authorization.
    • Enhanced user retrieval efficiency with a new DataLoader for activities.
    • Centralized Prettier configuration for consistent code formatting across the project.
  • Bug Fixes

    • Improved handling of user retrieval and activity processing in the UserService.
  • Documentation

    • Updated comments and documentation for new and modified methods to enhance clarity.
  • Tests

    • Expanded test coverage for the QuizService and UserService to validate various scenarios and error handling.
  • Chores

    • Cleaned up import statements and improved organization across multiple files.
    • Updated dependencies in package.json for improved performance and security.

@danielemery danielemery self-assigned this Dec 19, 2024
@danielemery danielemery linked an issue Dec 19, 2024 that may be closed by this pull request
Copy link

coderabbitai bot commented Dec 19, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces several configuration and code improvements across the project. The changes focus on updating linting and formatting configurations, enhancing error tracking with Sentry, refining service implementations, and introducing a new caching mechanism. The modifications span multiple files, including ESLint and Prettier configurations, package dependencies, and various service implementations. The updates aim to improve code quality, maintainability, and performance through more precise configurations and refined service logic.

Changes

File Change Summary
.eslintrc.js, .prettierrc.js Deleted configuration files
eslint.config.js New ESLint configuration file with recommended settings
prettier.config.js New Prettier configuration file
package.json Updated lint script, dependency versions, and removed TypeScript ESLint packages
src/activity/activity.gql.ts Added DataLoader for user activities
src/auth/authorisation.service.ts Added requireUserRole method
src/index.ts Updated Sentry error handling
src/instrument.ts Added config import for Sentry initialization
src/quiz/quiz.persistence.ts Updated method signature with QuizFilters
src/service.locator.ts Reintroduced config module for service initialization
src/user/user.service.ts Enhanced getUsers method with new overloads
src/util/cache.ts New Cache interface and MemoryCache implementation

Sequence Diagram

sequenceDiagram
    participant Client
    participant UserService
    participant UserPersistence
    participant Cache

    Client->>UserService: getUsers(first, sortedBy)
    UserService->>Cache: Check cached results
    alt Cache hit
        Cache-->>UserService: Return cached users
    else Cache miss
        UserService->>UserPersistence: Retrieve users
        UserPersistence-->>UserService: Return users
        UserService->>Cache: Store users in cache
    end
    UserService-->>Client: Return users
Loading

Poem

🐰 Lint and config, a rabbit's delight,
Cleaning code with systematic might
Sentry watches, cache keeps things neat
Dependencies dancing to a rhythmic beat
A project transformed, sleek and bright! 🔧✨

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


📜 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 fc61945 and 08b832a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (20)
  • .eslintrc.js (0 hunks)
  • .prettierrc.js (0 hunks)
  • eslint.config.js (1 hunks)
  • package.json (2 hunks)
  • prettier.config.js (1 hunks)
  • src/activity/activity.gql.ts (1 hunks)
  • src/auth/authorisation.service.ts (1 hunks)
  • src/index.ts (1 hunks)
  • src/instrument.ts (1 hunks)
  • src/quiz/quiz.gql.ts (1 hunks)
  • src/quiz/quiz.persistence.ts (1 hunks)
  • src/quiz/quiz.service.test.ts (1 hunks)
  • src/quiz/quiz.service.ts (3 hunks)
  • src/service.locator.ts (1 hunks)
  • src/statistics/statistics.service.test.ts (1 hunks)
  • src/user/user.gql.ts (1 hunks)
  • src/user/user.persistence.ts (1 hunks)
  • src/user/user.service.test.ts (1 hunks)
  • src/user/user.service.ts (1 hunks)
  • src/util/cache.ts (0 hunks)

🪧 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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

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

🔭 Outside diff range comments (1)
src/auth/authorisation.service.ts (1)

Line range hint 6-11: Enhance error handling and add defensive checks

While the implementation is functional, consider these improvements for robustness:

  1. Include the required role in the error message for better debugging
  2. Add null/undefined checks for context.roles

Consider applying these changes:

 requireUserRole(context: QuizlordContext, role: Role) {
+  if (!context?.roles) {
+    throw new UnauthorisedError('User roles are not available');
+  }
   if (!context.roles.includes(role)) {
-    throw new UnauthorisedError('You are not authorised to perform this action');
+    throw new UnauthorisedError(`This action requires the ${role} role`);
   }
 }
🧹 Nitpick comments (7)
src/quiz/quiz.service.test.ts (2)

Line range hint 14-29: Consider enhancing mock organization.

Consider extracting the mock implementations into a separate test helpers file to improve maintainability and reusability.

+ // Move to __test__/helpers/mocks.ts
+ export const createMockPersistence = () => ({
+   createQuizWithImages: jest.fn(),
+   getCompletionScoreWithQuizTypesForUser: jest.fn(),
+   getQuizzesWithUserResults: jest.fn(),
+   getQuizByIdWithResults: jest.fn(),
+   getRecentQuizCompletions: jest.fn(),
+   getRecentQuizUploads: jest.fn(),
+ });

Line range hint 37-41: Consider adding test lifecycle management.

Consider adding a common beforeAll setup and afterAll cleanup to manage test lifecycle consistently.

+ beforeAll(() => {
+   // Common test setup
+ });
+ 
+ afterAll(() => {
+   // Common test cleanup
+ });
src/service.locator.ts (1)

Line range hint 1-41: Consider dependency injection instead of service locator pattern

While the service locator pattern works, consider migrating to dependency injection for better testability and maintainability. The current pattern makes dependencies implicit and harder to mock in tests.

Benefits of switching to DI:

  1. Explicit dependencies
  2. Easier unit testing
  3. Better compile-time checking
  4. More maintainable codebase

Would you like assistance in planning this architectural improvement?

src/auth/authorisation.service.ts (1)

Line range hint 6-11: Consider caching role checks for performance

For high-traffic applications, consider implementing a caching strategy for role checks, especially if roles are fetched from a database. This could be particularly important if this method is called frequently within a request lifecycle.

src/activity/activity.gql.ts (1)

Line range hint 12-15: Consider adding error handling to the resolver

The resolver should handle potential errors from the DataLoader to prevent unhandled promise rejections from propagating to the GraphQL layer.

 async function activityFeedUser(parent: RecentActivityItem, _params: Record<string, never>, _context: QuizlordContext) {
-  return usersForActivityLoader.load(parent);
+  try {
+    return await usersForActivityLoader.load(parent);
+  } catch (error) {
+    console.error('Failed to load users for activity:', error);
+    throw new Error('Failed to load users for activity');
+  }
 }
src/user/user.service.ts (2)

Line range hint 52-89: Consider simplifying the overloaded method signatures

The current implementation uses method overloading to handle different sorting scenarios, which adds complexity to the codebase. Consider using a single method with an options object pattern for better maintainability.

interface GetUsersOptions {
  first: number;
  sortedBy: UserSortOption;
  currentUserId?: string;
  afterId?: string;
}

async getUsers(options: GetUsersOptions): Promise<GetUsersResult>

Line range hint 155-186: Well-structured batch processing implementation

The implementation of getUsersForActivities is well-structured with clear separation of concerns:

  1. Efficient filtering of activity items by type
  2. Parallel processing of quiz completions and uploads
  3. Proper type transformations

However, consider adding error handling for the persistence layer calls.

 async getUsersForActivities(activityItems: readonly RecentActivityItem[]): Promise<Record<string, User[]>> {
+  try {
     const quizCompletionActivityItems = activityItems.filter(
       (activityItem) => activityItem.actionType === 'QUIZ_COMPLETED',
     );
     // ... rest of the implementation ...
     return {
       ...quizCompletionUserMap,
       ...quizUploadUserMap,
     };
+  } catch (error) {
+    console.error('Failed to fetch users for activities:', error);
+    throw new Error('Failed to fetch users for activities');
+  }
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8ecf6ce and fc61945.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (20)
  • .eslintrc.js (0 hunks)
  • .prettierrc.js (0 hunks)
  • eslint.config.js (1 hunks)
  • package.json (2 hunks)
  • prettier.config.js (1 hunks)
  • src/activity/activity.gql.ts (1 hunks)
  • src/auth/authorisation.service.ts (1 hunks)
  • src/index.ts (1 hunks)
  • src/instrument.ts (1 hunks)
  • src/quiz/quiz.gql.ts (1 hunks)
  • src/quiz/quiz.persistence.ts (1 hunks)
  • src/quiz/quiz.service.test.ts (1 hunks)
  • src/quiz/quiz.service.ts (3 hunks)
  • src/service.locator.ts (1 hunks)
  • src/statistics/statistics.service.test.ts (1 hunks)
  • src/user/user.gql.ts (1 hunks)
  • src/user/user.persistence.ts (1 hunks)
  • src/user/user.service.test.ts (1 hunks)
  • src/user/user.service.ts (1 hunks)
  • src/util/cache.ts (0 hunks)
💤 Files with no reviewable changes (3)
  • .prettierrc.js
  • .eslintrc.js
  • src/util/cache.ts
✅ Files skipped from review due to trivial changes (7)
  • prettier.config.js
  • src/instrument.ts
  • eslint.config.js
  • src/user/user.gql.ts
  • src/quiz/quiz.gql.ts
  • src/user/user.persistence.ts
  • src/user/user.service.test.ts
🔇 Additional comments (16)
src/quiz/quiz.persistence.ts (1)

6-6: LGTM! Clean integration of QuizFilters type.

The addition of QuizFilters import enhances type safety and maintains proper separation of concerns.

src/quiz/quiz.service.ts (3)

10-10: LGTM! Clean import organization.

The import statements are well-organized and properly grouped.

Also applies to: 14-14


Line range hint 63-73: LGTM! Improved object destructuring pattern.

The destructuring pattern enhances code readability by clearly separating fields that require transformation.


Line range hint 300-309: LGTM! Consistent destructuring pattern.

The destructuring pattern in #quizPersistenceWithMyCompletionsToQuiz matches the pattern used in getQuizDetails, maintaining consistency.

src/quiz/quiz.service.test.ts (1)

1-8: LGTM! Clean import organization and proper mocking setup.

The imports and mock setup provide a solid foundation for testing.

src/service.locator.ts (3)

4-4: LGTM: Config import addition aligns with centralization effort

The addition of the config import aligns with the broader effort to centralize configuration management across the application.


Line range hint 18-19: Verify AUTH0 configuration handling

The authentication service is now using centralized config values, which is good. However, we should verify that these sensitive AUTH0 configurations are properly handled in the config module.

✅ Verification successful

Let me check how these configurations are actually loaded and validated by looking at the config module's implementation.


AUTH0 configuration is properly validated and handled

The config module implements proper validation for AUTH0_DOMAIN and AUTH0_AUDIENCE:

  • Both fields are marked as required
  • AUTH0_AUDIENCE specifically requires a valid URI format
  • The validation is enforced at startup with process termination on failure
  • Values are loaded from environment variables and validated against a strict schema
  • Unknown fields are allowed but stripped from the final config object
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check how AUTH0 configs are loaded/handled
rg -A 5 "AUTH0_(DOMAIN|AUDIENCE)" src/config/

Length of output: 909


Script:

#!/bin/bash
# Check the config module implementation for loading and validation
cat src/config/config.ts

Length of output: 1773


Line range hint 24-24: Verify AWS configuration handling

The S3FileService is using multiple AWS-related configurations. Let's verify these are properly handled and that sensitive credentials are managed securely.

✅ Verification successful

Let me gather more information about AWS configuration and credential handling.


Based on the gathered information, I can now provide the final response:

AWS configuration is properly handled with secure practices

The implementation follows secure practices for AWS configuration:

  • AWS credentials are managed through the default AWS SDK credential chain (no hardcoded credentials)
  • Configuration is properly validated using Joi schema in config.ts
  • S3Client is initialized with only the required region parameter
  • Sensitive operations use temporary credentials via presigned URLs with a 1-hour expiration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check AWS config handling
rg -A 5 "AWS_(REGION|BUCKET_NAME)" src/config/

# Check for any AWS credential handling
rg -i "aws.*credential" src/

Length of output: 931


Script:

#!/bin/bash
# Check for AWS SDK initialization and credential configuration
rg -A 5 "new AWS\." src/
rg -A 5 "AWS\.config" src/

# Check for environment variable loading related to AWS
rg -A 5 "process\.env\.AWS" src/

# Look for credential configuration in S3FileService
ast-grep --pattern 'class S3FileService {
  $$$
}'

Length of output: 2063

src/auth/authorisation.service.ts (2)

1-4: LGTM! Well-organized imports.

The imports follow a clean separation between external dependencies and internal modules.


Line range hint 6-11: Verify consistent usage of role validation

Let's ensure this method is being used consistently across all authenticated endpoints.

✅ Verification successful

Based on the results, I can now generate the final response:

Role validation is consistently implemented across all GraphQL resolvers

The requireUserRole check is properly implemented across all GraphQL resolvers in the codebase:

  • User resolvers in user.gql.ts
  • Quiz resolvers in quiz.gql.ts (create, complete, mark illegible, etc.)
  • Statistics resolver in statistics.gql.ts
  • Activity resolver in activity.gql.ts

All endpoints consistently validate the 'USER' role before proceeding with their operations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all GraphQL resolvers and verify role checks
# Look for resolver decorators and check if requireUserRole is used

# Search for GraphQL resolver methods
ast-grep --pattern 'class $_ {
  $$$
  @Resolver($$$)
  async $_($$$) {
    $$$
  }
  $$$
}'

# Search for requireUserRole usage
rg -A 3 'requireUserRole' 

Length of output: 3357

package.json (2)

14-14: LGTM: Lint script scope refinement

The lint script now specifically targets the ./src directory instead of the entire project, which is more efficient and aligns with common practices.


52-52: Verify compatibility with the new major versions

The updates include significant version changes:

  • @dtdot/eslint-config: ^1.0.1 (major)
  • eslint: ^8.57.1 (minor)
  • prettier: ^3.4.2 (minor)

Also applies to: 58-58, 61-61

✅ Verification successful

Let me try to gather more specific information about the package dependencies and their usage.


Let me check the actual ESLint and Prettier configurations to understand how they're being used.


ESLint and Prettier configurations are minimal and follow recommended presets

The project uses a simple configuration that extends @dtdot/eslint-config recommended presets without any custom overrides. The version bump should be safe as:

  • The ESLint config only uses the recommended preset with no custom rules
  • The Prettier config also uses the recommended preset without modifications
  • Both tools are only used for development/linting and don't affect runtime behavior
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for breaking changes in the updated packages

# Check the changelog for @dtdot/eslint-config
gh api repos/dtdot/eslint-config/releases | jq '.[0].body'

# Check ESLint migration guide for version 8
rg -A 5 "migration|upgrade|breaking" $(fd -t f . | grep -i changelog | grep -i eslint)

Length of output: 1681


Script:

#!/bin/bash
# Check current ESLint configuration and rules being used
fd -t f "\.eslintrc" -X cat

# Check for ESLint and Prettier related configurations in package.json
rg -A 5 "eslint|prettier" package.json

# Look for any ESLint or Prettier specific configurations or extends
fd -t f "\.js|\.json" -X rg -l "dtdot/eslint-config|eslintConfig|prettier"

Length of output: 827


Script:

#!/bin/bash
# Check the content of ESLint and Prettier config files
echo "=== ESLint Config ==="
cat eslint.config.js

echo -e "\n=== Prettier Config ==="
cat prettier.config.js

# Check for any existing ESLint errors in the codebase
echo -e "\n=== Current ESLint Issues ==="
npx eslint ./src --max-warnings 0 || true

Length of output: 758

src/index.ts (1)

4-4: LGTM: Import organization and Sentry integration

The imports have been reorganized and grouped logically, improving code organization. The addition of Sentry for error tracking is a good practice for production monitoring.

Also applies to: 11-11, 14-14, 16-16, 18-18, 19-19

src/statistics/statistics.service.test.ts (1)

3-5: LGTM: Import organization

The imports have been reordered to follow the new ESLint configuration rules.

src/activity/activity.gql.ts (1)

Line range hint 27-35: LGTM! Excellent performance optimization using DataLoader

The implementation of DataLoader for batching user requests is a great performance improvement. It will help reduce the N+1 query problem by batching multiple individual user requests into a single call.

A few positive observations:

  1. Proper use of readonly for the input parameter
  2. Clear mapping of results back to individual requests
  3. Handling of missing users by returning empty arrays
src/user/user.service.ts (1)

Line range hint 155-186: Verify the performance impact of Object.fromEntries transformations

The implementation uses multiple Object.fromEntries and Object.entries transformations. For large datasets, this could impact performance.

✅ Verification successful

Let me gather more context about the data flow and usage patterns to better assess the performance implications.


Let me try a different approach to understand the usage patterns and data flow.


Based on the gathered context, I can now provide a final response about the performance implications of the Object.fromEntries transformations.

Object transformations are acceptable for this use case

The implementation's use of Object.fromEntries and Object.entries is justified because:

  • The data volume is naturally limited as it processes recent activity items
  • The persistence layer shows that quiz completions and uploads are fetched with limits (see getRecentQuizCompletions and getRecentQuizUploads)
  • The transformations are necessary to map persistence models to domain models while preserving the activity item IDs as keys

The performance impact is negligible since:

  • The data structure is shallow (single-level object transformation)
  • The operation is performed on an already filtered subset of activity items
  • The transformation maintains necessary mapping between activity IDs and their associated users
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar patterns in the codebase to identify potential performance bottlenecks
rg -A 2 "Object\.fromEntries\(" 

Length of output: 501


Script:

#!/bin/bash
# Check the persistence layer implementation to understand data volume
ast-grep --pattern 'getUsersForQuizCompletions($_) {
  $$$
}'

# Check for any test files that might indicate data volume
rg -l "getUsersForActivities.*test" 

# Look for any configuration or constants that might indicate expected data volumes
rg "MAX_.*QUIZ|LIMIT.*QUIZ" 

Length of output: 131


Script:

#!/bin/bash
# Look for test files related to user service
fd -e test.ts -e spec.ts user.service

# Check for activity-related interfaces or types to understand data structure
rg -A 5 "interface.*Activity|type.*Activity"

# Look for persistence layer implementation
fd persistence.ts -x cat {}

Length of output: 14710

@danielemery danielemery force-pushed the 95-update-to-100-release-of-dtdoteslint-config branch from fc61945 to 08b832a Compare December 23, 2024 15:24
@codecov-commenter
Copy link

Codecov Report

Attention: Patch coverage is 33.33333% with 8 lines in your changes missing coverage. Please review.

Project coverage is 34.16%. Comparing base (f8f1c3e) to head (08b832a).

Files with missing lines Patch % Lines
src/index.ts 0.00% 5 Missing ⚠️
src/quiz/quiz.gql.ts 0.00% 1 Missing ⚠️
src/service.locator.ts 0.00% 1 Missing ⚠️
src/user/user.gql.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #150   +/-   ##
=======================================
  Coverage   34.16%   34.16%           
=======================================
  Files          26       26           
  Lines         600      600           
  Branches       87       93    +6     
=======================================
  Hits          205      205           
  Misses        395      395           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@danielemery danielemery merged commit a6afa67 into main Dec 23, 2024
4 of 5 checks passed
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.

Update to 1.0.0 release of @dtdot/eslint-config
2 participants