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

refactor: ♻️ Create a ConfigModule that exposes a ConfigService which loads the appropriate .env file #28

Merged
merged 8 commits into from
Nov 13, 2024

Conversation

zhumeisongsong
Copy link
Owner

@zhumeisongsong zhumeisongsong commented Nov 13, 2024

Closes: #29

Summary by CodeRabbit

  • New Features

    • Introduced dynamic configuration management for various services using environment variables.
    • Added new database configuration settings.
  • Bug Fixes

    • Updated host configurations for services to use explicit URLs.
  • Documentation

    • Created a new project configuration file for better management.
  • Tests

    • Added unit tests for configuration settings to ensure correct behavior with environment variables.
  • Chores

    • Updated dependencies to include the latest version of @nestjs/config and zod.
    • Removed outdated configuration and test files to streamline the project.

Copy link

coderabbitai bot commented Nov 13, 2024

Walkthrough

The pull request introduces significant changes across multiple files, primarily focusing on updating configuration management for a NestJS application. Key modifications include the transition from static to dynamic configuration using the ConfigModule and ConfigService, allowing for runtime retrieval of environment variables. Additionally, new environment variables are added to the .env.sample file, and several files related to application configuration and testing have been deleted. The changes aim to enhance flexibility and maintainability in managing application settings.

Changes

File Change Summary
.env.sample Added new variables: PROTOCOL=http, DATABASE_HOST=127.0.0.1, DATABASE_PORT=3306; existing variables remain unchanged.
apps/gateway/src/app/app.module.ts Replaced static GraphQLModule configuration with dynamic forRootAsync using ConfigService; removed static gateway configuration.
apps/gateway/src/main.ts Updated bootstrap function to use ConfigService for retrieving host, port, and protocol instead of direct imports from gatewayConfig.
apps/users-application/src/app/app.module.ts Added global ConfigModule to load userAppConfig.
apps/users-application/src/main.ts Updated bootstrap function to use ConfigService for obtaining host, port, and protocol from userApp.
libs/application-config/project.json Deleted project.json, removing structured metadata for the applications-config library.
libs/application-config/src/index.ts Deleted index.ts, which re-exported modules from applications-config and subgraphs-config.
libs/application-config/src/lib/applications-config.spec.ts Deleted unit tests for service configurations related to environment variables.
libs/application-config/src/lib/applications-config.ts Deleted interface and constants related to application configuration.
libs/application-config/src/lib/subgraphs-config.spec.ts Deleted test suite for subgraphsConfig functionality.
libs/application-config/src/lib/subgraphs-config.ts Deleted configuration for subgraphs used in Apollo Gateway setup.
libs/config/jest.config.ts Updated displayName and coverageDirectory to reflect new naming convention.
libs/config/project.json Created new project.json defining the project as a library named "config".
libs/config/src/index.ts Added exports for applications.config and database.config.
libs/config/src/lib/applications.config.spec.ts Introduced new test suite for gatewayConfig and userAppConfig.
libs/config/src/lib/applications.config.ts Introduced configuration management for the application using registerAs, defining gatewayConfig and userAppConfig.
libs/config/src/lib/database.config.spec.ts Added new test suite for databaseConfig function.
libs/config/src/lib/database.config.ts Introduced databaseConfig function for dynamic database connection parameters.
package.json Added dependencies for @nestjs/config and zod.
tsconfig.base.json Updated path mapping from @graphql-federation-workspace/applications-config to @libs/config.

Possibly related PRs

  • feat: ✨ add applicaiton config #7: Changes in this PR involve modifications to the .env.sample file, specifically adding and updating environment variables related to service hosts.
  • feat: ✨ Initial graphql federation: users application #14: This PR introduces changes to the main.ts file of the users application, where it retrieves configuration values from environment variables. The main PR also adds new environment variables, including PROTOCOL, which will be utilized in the application configuration.

🐇 In the land of code, where changes bloom,
New configs sprout, dispelling the gloom.
With hosts now clear, and ports in sight,
Our services dance, all set to ignite!
So hop along, let’s celebrate this spree,
For a brighter future, as sweet as can be! 🌼✨


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.

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: 12

🧹 Outside diff range and nitpick comments (11)
.env.sample (2)

10-11: Consider security implications of default database credentials

While it's common to provide example credentials in .env.sample, consider:

  1. Adding a comment to explicitly mark these as example values
  2. Using a more obvious placeholder format (e.g., <your-db-user>)

This helps prevent accidental use of test credentials in production.

-DATABASE_USER=test
-DATABASE_PASSWORD=test
+# Example credentials - DO NOT use in production
+DATABASE_USER=<your-db-user>
+DATABASE_PASSWORD=<your-db-password>

1-11: Add descriptive comments for configuration variables

To improve maintainability, consider adding comments to describe:

  • The purpose of each variable
  • Expected value formats
  • Any constraints or requirements
+# Gateway service configuration
 GATEWAY_HOST=http://localhost
 GATEWAY_PORT=3333

+# User service configuration
 USER_HOST=http://localhost
 USER_PORT=15001

+# Task service configuration
 TASK_HOST=http://localhost
 TASK_PORT=15002

+# Database connection credentials
+# Note: Replace these values in your actual .env file
 DATABASE_USER=test
 DATABASE_PASSWORD=test
libs/config/src/lib/database.config.ts (1)

4-5: Use consistent environment variable access pattern.

The code uses different patterns for accessing environment variables - direct access for HOST and nullish coalescing for PORT.

Consider standardizing the access pattern:

 export const databaseConfig = registerAs('database', () => ({
-  host: process.env['DATABASE_HOST'],
-  port: process.env['DATABASE_PORT'] || 5432,
+  host: process.env['DATABASE_HOST'] ?? '',
+  port: process.env['DATABASE_PORT'] ?? 5432,
 }));
apps/users-application/src/app/app.module.ts (1)

11-14: Consider adding configuration validation.

To ensure runtime type safety and validation of environment variables, consider adding Joi validation schema to the ConfigModule.

Example implementation:

import * as Joi from 'joi';

ConfigModule.forRoot({
  isGlobal: true,
  load: [userAppConfig],
  validationSchema: Joi.object({
    DATABASE_USER: Joi.string().required(),
    DATABASE_PASSWORD: Joi.string().required(),
    // Add other environment variables
  }),
  validationOptions: {
    allowUnknown: true,
    abortEarly: true,
  },
});
libs/config/src/lib/applications.config.ts (1)

3-9: Consider making the default configuration more flexible

A few suggestions to improve the default configuration:

  1. Consider separating protocol from host to allow for different protocols (http/https)
  2. Consider using numbers instead of strings for port values
  3. Consider moving default ports to environment variables
-const DEFAULT_HOST = 'http://localhost';
+const DEFAULT_PROTOCOL = process.env['DEFAULT_PROTOCOL'] ?? 'http';
+const DEFAULT_HOST = `${DEFAULT_PROTOCOL}://localhost`;

 const DEFAULT_PORT = {
-  user: '15001',
-  task: '15002',
-  gateway: '3333',
+  user: parseInt(process.env['DEFAULT_USER_PORT'] ?? '15001', 10),
+  task: parseInt(process.env['DEFAULT_TASK_PORT'] ?? '15002', 10),
+  gateway: parseInt(process.env['DEFAULT_GATEWAY_PORT'] ?? '3333', 10),
 };
apps/users-application/src/main.ts (1)

21-21: Consider enhancing the startup logging.

While the current logging is functional, consider adding more detailed logging for better debugging and monitoring capabilities.

- Logger.log(`🚀 Application is running on: ${host}:${port}`);
+ Logger.log(
+   `🚀 Application is running on: ${host}:${port}`,
+   'Bootstrap'
+ );
+ Logger.debug(
+   `Environment: ${configService.get('NODE_ENV')}`,
+   'Bootstrap'
+ );
tsconfig.base.json (1)

18-19: Consider adding a comment to document the config module's purpose.

For better maintainability, consider adding a comment above the path mapping to document the purpose of this configuration module.

+      // Path alias for the centralized configuration module that handles environment variables
       "@libs/config": [
         "libs/config/src/index.ts"
       ],
libs/config/src/lib/database.config.spec.ts (2)

3-13: Consider enhancing test setup robustness.

While the current setup/teardown logic is good, consider these improvements:

  1. Add type safety to the environment backup
  2. Ensure complete cleanup in afterAll
-  const OLD_ENV = process.env;
+  const OLD_ENV: NodeJS.ProcessEnv = { ...process.env };

   beforeEach(() => {
     jest.resetModules();
-    process.env = { ...OLD_ENV };
+    process.env = { ...OLD_ENV }; // Make a shallow copy
   });

   afterAll(() => {
-    process.env = OLD_ENV;
+    process.env = { ...OLD_ENV }; // Restore using a fresh copy
+    jest.resetModules(); // Clean up module cache after all tests
   });

1-32: Add error handling test cases.

Consider adding these test scenarios:

  1. Invalid port number handling
  2. Missing required configuration
  it('should throw error for invalid port number', () => {
    process.env['DATABASE_PORT'] = 'invalid';
    
    expect(() => databaseConfig()).toThrow('Invalid port number');
  });

  it('should throw error for missing required host', () => {
    process.env['DATABASE_HOST'] = '';
    
    expect(() => databaseConfig()).toThrow('Database host is required');
  });
🧰 Tools
🪛 Biome

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

libs/config/src/lib/applications.config.spec.ts (1)

4-20: LGTM with a performance optimization suggestion.

The test cases thoroughly verify both default and environment-specific configurations. However, there's a performance optimization opportunity in the environment cleanup.

Consider replacing the delete operator with undefined assignments for better performance:

-      delete process.env['GATEWAY_HOST'];
-      delete process.env['GATEWAY_PORT'];
+      process.env['GATEWAY_HOST'] = undefined;
+      process.env['GATEWAY_PORT'] = undefined;
🧰 Tools
🪛 Biome

[error] 17-17: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 18-18: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

apps/gateway/src/app/app.module.ts (1)

24-24: Redundant 'driver' option inside 'useFactory'

The driver option is already specified in the options passed to forRootAsync (line 20). Including driver: ApolloGatewayDriver inside the useFactory return value (line 24) is redundant.

Consider removing the redundant driver from the return value in useFactory to avoid redundancy.

Apply this diff:

 return {
-  driver: ApolloGatewayDriver,
   gateway: {
     // ...
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9775dac and 9bcbec8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • .env.sample (1 hunks)
  • apps/gateway/src/app/app.module.ts (1 hunks)
  • apps/gateway/src/main.ts (1 hunks)
  • apps/users-application/src/app/app.module.ts (1 hunks)
  • apps/users-application/src/main.ts (1 hunks)
  • libs/application-config/project.json (0 hunks)
  • libs/application-config/src/index.ts (0 hunks)
  • libs/application-config/src/lib/applications-config.spec.ts (0 hunks)
  • libs/application-config/src/lib/applications-config.ts (0 hunks)
  • libs/application-config/src/lib/subgraphs-config.spec.ts (0 hunks)
  • libs/application-config/src/lib/subgraphs-config.ts (0 hunks)
  • libs/config/jest.config.ts (1 hunks)
  • libs/config/project.json (1 hunks)
  • libs/config/src/index.ts (1 hunks)
  • libs/config/src/lib/applications.config.spec.ts (1 hunks)
  • libs/config/src/lib/applications.config.ts (1 hunks)
  • libs/config/src/lib/database.config.spec.ts (1 hunks)
  • libs/config/src/lib/database.config.ts (1 hunks)
  • package.json (1 hunks)
  • tsconfig.base.json (1 hunks)
💤 Files with no reviewable changes (6)
  • libs/application-config/project.json
  • libs/application-config/src/index.ts
  • libs/application-config/src/lib/applications-config.spec.ts
  • libs/application-config/src/lib/applications-config.ts
  • libs/application-config/src/lib/subgraphs-config.spec.ts
  • libs/application-config/src/lib/subgraphs-config.ts
✅ Files skipped from review due to trivial changes (2)
  • libs/config/project.json
  • libs/config/src/index.ts
🧰 Additional context used
🪛 Biome
libs/config/src/lib/applications.config.spec.ts

[error] 17-17: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 18-18: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 37-37: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 38-38: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

libs/config/src/lib/database.config.spec.ts

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🔇 Additional comments (17)
.env.sample (1)

1-1: LGTM! Consistent URL format across services

The change to include http:// protocol prefix in host URLs is a good practice as it:

  • Makes the protocol explicit
  • Ensures consistency across service configurations
  • Prevents potential connection issues

Also applies to: 4-4, 7-7

libs/config/src/lib/database.config.ts (2)

1-1: LGTM! Clean import statement.

The import of registerAs from @nestjs/config follows NestJS best practices for configuration management.


3-6: Consider adding additional database configuration options.

The current configuration might be incomplete for establishing a database connection.

Let's check what other database configuration files might exist:

Consider adding these common database configuration options:

 export const databaseConfig = registerAs('database', () => ({
   host: process.env['DATABASE_HOST'],
   port: process.env['DATABASE_PORT'] || 5432,
+  username: process.env['DATABASE_USER'],
+  password: process.env['DATABASE_PASSWORD'],
+  database: process.env['DATABASE_NAME'],
+  ssl: process.env['DATABASE_SSL'] === 'true',
 }));
libs/config/jest.config.ts (1)

2-2: Verify the library renaming impact

The display name change from 'applications-config' to 'config' looks good, but let's ensure all related configurations and imports are updated consistently.

apps/users-application/src/app/app.module.ts (2)

1-1: LGTM! Clean implementation of NestJS ConfigModule.

The implementation follows NestJS best practices for configuration management, making the configuration globally available and loading it through a dedicated config file.

Let's verify the userAppConfig implementation:

Also applies to: 3-3, 11-14


10-16: Verify the order of module imports.

The current order (ConfigModule before UsersModule) is correct as it ensures configuration is available before other modules are initialized. This is particularly important if UsersModule depends on any configuration values.

Let's verify if UsersModule depends on ConfigService:

✅ Verification successful

Please execute the following script to verify if UsersModule depends on ConfigService:


Verified: UsersModule does not depend on ConfigService, so the current module import order is appropriate.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if UsersModule uses ConfigService
# Expected: Find any usage of ConfigService in UsersModule

rg -l "ConfigService" "apps/users-application/src/users/"

Length of output: 253


Script:

#!/bin/bash
# Description: Check if UsersModule uses ConfigService
# Expected: Find any usage of ConfigService in UsersModule

rg -l "ConfigService" "apps/users-application/src/users/"

Length of output: 55

apps/users-application/src/main.ts (1)

7-7: LGTM! Import changes align with ConfigModule implementation.

The addition of ConfigService import is appropriate for the new configuration management approach.

apps/gateway/src/main.ts (3)

7-7: LGTM!

The ConfigService import is correctly added and necessary for the dynamic configuration approach.


21-21: LGTM!

The logging message is correctly updated to use the new configuration values while maintaining the same informative format.


15-18: Verify configuration module setup

Let's ensure that the gateway configuration is properly set up in the application module and environment files.

tsconfig.base.json (1)

18-19: Verify all imports are updated to use the new path alias.

The path mapping change from @graphql-federation-workspace/applications-config to @libs/config looks good and follows a cleaner naming convention. However, this is a breaking change that requires updates to all existing imports.

Let's verify that all imports have been updated:

✅ Verification successful

All imports have been successfully updated to use the new path alias.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of the old import path
# and verify the new import path is being used correctly

# Check for any remaining references to the old path
echo "Checking for old import path usage..."
rg "@graphql-federation-workspace/applications-config"

# Check usage of new import path to ensure it's being used
echo "Checking new import path usage..."
rg "@libs/config"

Length of output: 464

libs/config/src/lib/applications.config.spec.ts (2)

1-3: LGTM! Well-structured test organization.

The test file follows good practices with clear imports and proper test hierarchy using describe blocks.


22-40: Verify the default port number and optimize cleanup.

The test cases provide good coverage, but there are two points to consider:

  1. The default port '15001' seems like a magic number. Please verify if this is documented somewhere.
  2. The environment cleanup can be optimized for performance.

Let's verify if the port number is documented:

Consider replacing the delete operator with undefined assignments:

-      delete process.env['USER_HOST'];
-      delete process.env['USER_PORT'];
+      process.env['USER_HOST'] = undefined;
+      process.env['USER_PORT'] = undefined;
✅ Verification successful

Default port number is properly documented.

The default port number '15001' is defined as a constant in libs/config/src/lib/applications.config.ts, addressing the magic number concern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for documentation of port 15001
rg -i "15001|default.*port" --type md

Length of output: 39


Script:

#!/bin/bash
# Search for documentation of port 15001 in all files and comments
rg -i "15001|default.*port"

Length of output: 864

🧰 Tools
🪛 Biome

[error] 37-37: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 38-38: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

apps/gateway/src/app/app.module.ts (4)

2-2: Imports are correctly updated for configuration management

The necessary modules and configurations are imported properly from '@libs/config' and '@nestjs/config'.

Also applies to: 5-5


13-16: ConfigModule is correctly set up with global configurations

The ConfigModule is configured as global and correctly loads the necessary configurations using the load option.


17-20: GraphQLModule is properly configured to use asynchronous factory

The GraphQLModule is correctly set up using forRootAsync with proper imports, injection, and driver configuration for dynamic configuration.


22-22: Ensure correct retrieval of 'userAppConfig'

Verify that the configuration key 'userApp' used in configService.get('userApp') matches the structure of the configuration object returned by userAppConfig.

If userAppConfig returns an object like { userApp: {...} }, then configService.get('userApp') is correct. Otherwise, adjust the key accordingly.

Let me know if you need assistance confirming the configuration keys.

libs/config/src/lib/database.config.ts Outdated Show resolved Hide resolved
libs/config/jest.config.ts Show resolved Hide resolved
libs/config/src/lib/applications.config.ts Outdated Show resolved Hide resolved
libs/config/src/lib/applications.config.ts Outdated Show resolved Hide resolved
libs/config/src/lib/applications.config.ts Outdated Show resolved Hide resolved
apps/gateway/src/main.ts Outdated Show resolved Hide resolved
libs/config/src/lib/database.config.spec.ts Outdated Show resolved Hide resolved
libs/config/src/lib/database.config.spec.ts Show resolved Hide resolved
package.json Show resolved Hide resolved
apps/gateway/src/app/app.module.ts Outdated Show resolved Hide resolved
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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9bcbec8 and ae34fe3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • libs/config/src/lib/database.config.ts (1 hunks)
  • package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🔇 Additional comments (1)
libs/config/src/lib/database.config.ts (1)

9-9: LGTM! Good use of type inference

The type inference from the Zod schema ensures type safety and maintainability.

libs/config/src/lib/database.config.ts Show resolved Hide resolved
libs/config/src/lib/database.config.ts Show resolved Hide resolved
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: 6

🧹 Outside diff range and nitpick comments (2)
libs/config/src/lib/applications.config.ts (1)

17-22: Consider making the service name configurable

The static 'name' property should either be moved to constants or made configurable via environment variables:

+const enum ServiceName {
+  User = 'user'
+}
+
+interface UserServiceConfig extends ServiceConfig {
+  name: string;
+}
+
-export const userAppConfig = registerAs('userApp', () => ({
+export const userAppConfig = registerAs('userApp', (): UserServiceConfig => ({
   protocol: process.env['PROTOCOL'] ?? DEFAULT_PROTOCOL,
   host: process.env['USER_HOST'] ?? DEFAULT_HOST,
-  port: process.env['USER_PORT'] ?? DEFAULT_PORT.user,
-  name: 'user',
+  port: validatePort(process.env['USER_PORT'] ?? DEFAULT_PORT.user),
+  name: process.env['USER_APP_NAME'] ?? ServiceName.User,
}));
libs/config/src/lib/database.config.spec.ts (1)

3-32: Consider adding tests for environment-specific configurations.

The test suite should be expanded to cover:

  1. Loading of different .env files based on NODE_ENV
  2. Error handling for invalid configurations
  3. Integration with NestJS's ConfigModule

This aligns with the PR's objective of creating a ConfigModule that loads appropriate .env files.

Would you like me to help create additional test cases for these scenarios?

🧰 Tools
🪛 Biome

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ae34fe3 and 66c0681.

📒 Files selected for processing (7)
  • .env.sample (1 hunks)
  • apps/gateway/src/app/app.module.ts (1 hunks)
  • apps/gateway/src/main.ts (1 hunks)
  • apps/users-application/src/main.ts (1 hunks)
  • libs/config/src/lib/applications.config.spec.ts (1 hunks)
  • libs/config/src/lib/applications.config.ts (1 hunks)
  • libs/config/src/lib/database.config.spec.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .env.sample
  • apps/gateway/src/main.ts
  • apps/users-application/src/main.ts
🧰 Additional context used
🪛 Biome
libs/config/src/lib/applications.config.spec.ts

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 27-27: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 28-28: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 56-56: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 57-57: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 58-58: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

libs/config/src/lib/database.config.spec.ts

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🔇 Additional comments (8)
libs/config/src/lib/database.config.spec.ts (3)

1-13: LGTM! Well-structured test setup.

The test setup follows best practices by properly managing environment variables and ensuring test isolation.


15-22: Expand test coverage for complete configuration validation.

While the current test correctly validates host and port, it should be expanded to verify all configuration properties provided by the service.

The previous review already suggested this improvement. Since that comment is still valid, I'll skip proposing the same changes again.


24-31: Replace delete operator with undefined assignment.

Using the delete operator can impact performance. Consider using undefined assignment instead.

The previous review already suggested this improvement along with additional test cases for default values. Since that comment is still valid, I'll skip proposing the same changes again.

🧰 Tools
🪛 Biome

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

apps/gateway/src/app/app.module.ts (3)

13-16: LGTM! ConfigModule setup follows best practices

The configuration is properly structured with global scope and separate config files for different concerns.


17-22: LGTM! GraphQLModule async configuration is well structured

The async configuration is properly implemented with dependency injection and factory pattern.


26-33: Verify single subgraph setup

The configuration shows only one subgraph. If this is a federation setup, typically multiple subgraphs would be expected.

✅ Verification successful

Single subgraph configuration confirmed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other potential subgraph definitions or documentation
rg -l "subgraphs" --type ts

Length of output: 62

libs/config/src/lib/applications.config.spec.ts (2)

1-3: LGTM! Well-structured test organization.

The test suite follows good testing practices with clear imports and a well-organized structure.


1-61: Consider adding more test coverage.

To fully validate the ConfigModule's functionality, consider adding test cases for:

  1. Invalid environment variable values
  2. Type conversion and validation
  3. Missing .env file scenarios
  4. Multiple environment configurations (development, production, etc.)

Would you like me to help create these additional test cases?

🧰 Tools
🪛 Biome

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 27-27: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 28-28: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 56-56: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 57-57: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 58-58: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

libs/config/src/lib/applications.config.ts Outdated Show resolved Hide resolved
libs/config/src/lib/applications.config.ts Outdated Show resolved Hide resolved
libs/config/src/lib/applications.config.ts Outdated Show resolved Hide resolved
apps/gateway/src/app/app.module.ts Show resolved Hide resolved
libs/config/src/lib/applications.config.spec.ts Outdated Show resolved Hide resolved
libs/config/src/lib/applications.config.spec.ts Outdated Show resolved Hide resolved
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: 2

🧹 Outside diff range and nitpick comments (3)
libs/config/src/lib/applications.config.ts (2)

3-8: Add JSDoc documentation and consider using Zod for validation

The ServiceConfig interface would benefit from documentation and runtime validation.

Add documentation and implement Zod validation:

import { z } from 'zod';

/** Configuration interface for service-specific settings */
const serviceConfigSchema = z.object({
  /** Protocol used for service communication (e.g., 'http', 'https') */
  protocol: z.string(),
  /** Hostname where the service is running */
  host: z.string(),
  /** Port number the service listens on (1-65535) */
  port: z.number().int().min(1).max(65535),
  /** Optional service name identifier */
  name: z.string().optional(),
});

type ServiceConfig = z.infer<typeof serviceConfigSchema>;

10-16: Document constants and consider using enums

The constants could benefit from documentation and stronger typing.

Consider this enhancement:

/** Default protocol for service communication */
const enum Protocol {
  Default = 'http'
}

/** Default hostname for local development */
const enum Host {
  Default = 'localhost'
}

/** Default port numbers for each service */
const DEFAULT_PORT = {
  user: 15001,
  task: 15002,
  gateway: 3333,
} as const satisfies Record<'user' | 'task' | 'gateway', number>;
libs/config/src/lib/applications.config.spec.ts (1)

32-60: Enhance test coverage for edge cases.

While the basic functionality is tested and past comments addressed the cleanup and 'name' property configurability, consider adding test cases for:

  1. Invalid port numbers (non-numeric strings, negative numbers)
  2. Missing or malformed protocol values
  3. Partial environment variable sets (what happens when only some variables are set?)

Example test case:

it('should handle partial environment variable sets', () => {
  process.env['USER_HOST'] = 'partial.example.com';
  const config = userAppConfig();
  expect(config).toEqual({
    protocol: 'http', // default
    host: 'partial.example.com', // from env
    port: 15001, // default
    name: 'user', // default
  });
});
🧰 Tools
🪛 Biome

[error] 56-56: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 57-57: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 58-58: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 66c0681 and bb73162.

📒 Files selected for processing (2)
  • libs/config/src/lib/applications.config.spec.ts (1 hunks)
  • libs/config/src/lib/applications.config.ts (1 hunks)
🧰 Additional context used
🪛 Biome
libs/config/src/lib/applications.config.spec.ts

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 27-27: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 28-28: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 56-56: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 57-57: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 58-58: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🔇 Additional comments (2)
libs/config/src/lib/applications.config.ts (1)

21-23: Verify environment variables documentation

Ensure all environment variables are documented in .env.sample.

Also applies to: 32-34

✅ Verification successful

Let me verify if USER_NAME is actually used in the codebase since it was flagged as missing.


I can now generate the final response since I have confirmed that USER_NAME was incorrectly included in the verification. Looking at the config file, I can see all environment variables have default values and the actual variables used are PROTOCOL, GATEWAY_HOST, GATEWAY_PORT, USER_HOST, and USER_PORT.

Environment variables are properly handled with defaults

All environment variables used in the configuration have fallback values:

  • PROTOCOL defaults to 'http'
  • GATEWAY_HOST/USER_HOST defaults to 'localhost'
  • GATEWAY_PORT defaults to 3333
  • USER_PORT defaults to 15001

The verification script shows these variables are documented in .env.sample. USER_NAME was incorrectly included in the verification as it's not used in the configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all environment variables are documented in .env.sample

required_vars=(
  "PROTOCOL"
  "GATEWAY_HOST"
  "GATEWAY_PORT"
  "USER_HOST"
  "USER_PORT"
  "USER_NAME"
)

echo "Checking .env.sample for required variables..."
for var in "${required_vars[@]}"; do
  if ! rg "^$var=" .env.sample > /dev/null; then
    echo "❌ Missing $var in .env.sample"
  fi
done

Length of output: 677


Script:

#!/bin/bash
# Check if USER_NAME is used in the codebase
rg "USER_NAME" -A 2 -B 2

# Also check the config file for any other env vars we should verify
cat libs/config/src/lib/applications.config.ts

Length of output: 1022

libs/config/src/lib/applications.config.spec.ts (1)

4-30: 🛠️ Refactor suggestion

Improve test reliability with proper test isolation.

The test suite should be refactored to ensure proper test isolation and cleanup. While the past review comments already suggested moving cleanup to afterEach, it's worth noting that the current approach could lead to test pollution if any test fails before cleanup.

Additionally, consider adding test cases for:

  • Invalid port numbers
  • Empty string values
  • Special characters in host names
🧰 Tools
🪛 Biome

[error] 26-26: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 27-27: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 28-28: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

libs/config/src/lib/applications.config.ts Show resolved Hide resolved
libs/config/src/lib/applications.config.ts Show resolved Hide resolved
@zhumeisongsong zhumeisongsong merged commit 88aa529 into main Nov 13, 2024
5 checks passed
@zhumeisongsong zhumeisongsong deleted the feature/nestjs-config branch November 13, 2024 06:48
@zhumeisongsong zhumeisongsong changed the title ♻️ Create a ConfigModule that exposes a ConfigService which loads the appropriate .env file refactor: ♻️ Create a ConfigModule that exposes a ConfigService which loads the appropriate .env file Nov 13, 2024
Copy link

🎉 This PR is included in version 1.0.0 🎉

The release is available on GitHub release

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.

✨ Configuration of @nestjs/config
1 participant