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

feat: generate destination constants #1800

Merged
merged 16 commits into from
Nov 19, 2024

Conversation

koladilip
Copy link
Collaborator

@koladilip koladilip commented Nov 14, 2024

What are the changes introduced in this PR?

Add templates for various languages and script to generate constants

What is the related Linear task?

Resolves INT-2900

Please explain the objectives of your changes below

Put down any required details on the broader aspect of your changes. If there are any dependent changes, mandatorily mention them here

Any changes to existing capabilities/behaviour, mention the reason & what are the changes ?

N/A

Any new dependencies introduced with this change?

N/A

Any new checks got introduced or modified in test suites. Please explain the changes.

N/A


Developer checklist

  • My code follows the style guidelines of this project

  • No breaking changes are being introduced.

  • All related docs linked with the PR?

  • All changes manually tested?

  • Any documentation changes needed with this change?

  • I have executed schemaGenerator tests and updated schema if needed

  • Are sensitive fields marked as secret in definition config?

  • My test cases and placeholders use only masked/sample values for sensitive fields

  • Is the PR limited to 10 file changes & one task?

Reviewer checklist

  • Is the type of change in the PR title appropriate as per the changes?

  • Verified that there are no credentials or confidential data exposed with the changes.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new script for generating constants based on templates, enhancing configuration management.
    • Added new files for device mode destinations in various programming languages (Dart, Java, Kotlin, Objective-C, Swift, TypeScript), each containing dynamically generated constants for destination names and display names.
  • Bug Fixes

    • Corrected JSON formatting in the package.json file.
  • Documentation

    • Added comments in generated files indicating they are auto-generated and should not be edited manually.

Copy link

coderabbitai bot commented Nov 14, 2024

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (6)
  • generated/Destinations.dart is excluded by !**/generated/**
  • generated/Destinations.java is excluded by !**/generated/**
  • generated/Destinations.kt is excluded by !**/generated/**
  • generated/Destinations.m is excluded by !**/generated/**
  • generated/Destinations.swift is excluded by !**/generated/**
  • generated/Destinations.ts is excluded by !**/generated/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request introduces a new script in the package.json for generating constants related to device mode destinations. It includes the creation of a dedicated Node.js script, generateConstants.js, which processes templates to dynamically generate destination constants in various programming languages. Additionally, several template files for Dart, Java, Kotlin, Objective-C, Swift, and TypeScript are added, each defining a Destinations class or structure with corresponding constants. The changes ensure that the constants are auto-generated and maintain a consistent structure across languages.

Changes

File Change Summary
package.json - New script added: "generate:constants": "node scripts/generateConstants.js"
- Updated "pre-process" script for proper JSON formatting.
scripts/generateConstants.js - Introduced a script for generating configuration files based on templates with dynamic constants.
templates/Destinations.dart.template - New file generated: Destinations.dart with a class for device mode destinations constants.
templates/Destinations.java.template - New file generated: Destinations.java with a public class for device mode destinations constants.
templates/Destinations.kt.template - New file generated: Destinations.kt with an object for device mode destinations constants.
templates/Destinations.m.template - New files generated for Destinations class in Objective-C with constants for destinations.
templates/Destinations.swift.template - New file generated: Destinations.swift with a structure for device mode destinations constants.
templates/Destinations.ts.template - New template file introduced for generating a TypeScript file with constants for destinations.

Possibly related PRs

  • feat: onboard tune destination #1744: The changes in this PR involve the onboarding of a new destination, which may relate to the generation of constants for destinations as seen in the main PR's generateConstants.js script.

Suggested reviewers

  • lvrach
  • am6010
  • AchuthaSourabhC
  • krishna2020
  • ssbeefeater
  • debanjan97
  • cisse21
  • ruchiramoitra
  • 1abhishekpandey
  • ItsSudip
  • shrouti1507
  • utsabc
  • sandeepdsvs

🐰 In the garden, constants bloom,
With scripts and templates, we make room.
From Dart to Swift, they take their flight,
Auto-generated, oh what a sight!
With every name and display so bright,
Our destinations shine, a pure delight! 🌼


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

codecov bot commented Nov 14, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (a039627) to head (5b121c6).
Report is 1 commits behind head on develop.

Additional details and impacted files
@@            Coverage Diff            @@
##           develop     #1800   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            2         2           
  Lines           53        53           
  Branches         7         7           
=========================================
  Hits            53        53           

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


🚨 Try these New Features:

saikumarrs
saikumarrs previously approved these changes Nov 18, 2024
@koladilip koladilip marked this pull request as ready for review November 18, 2024 10:38
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)
scripts/generateConstants.js (2)

1-7: Consider modernizing the code with ES modules and TypeScript

The code currently uses CommonJS require statements. Consider modernizing by:

  1. Using ES modules (import/export)
  2. Adding TypeScript for better type safety and maintainability
-const fs = require('fs');
-const path = require('path');
+import * as fs from 'fs';
+import * as path from 'path';
🧰 Tools
🪛 eslint

[error] 1-1: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


9-14: Consider enhancing language mapping configuration

The current hardcoded language mapping could be improved by:

  1. Moving it to a separate configuration file for easier maintenance
  2. Adding type definitions for platforms and language codes
  3. Adding validation for supported language codes

Consider creating a separate config.ts file:

export interface PlatformConfig {
  [platform: string]: string[];
}

export const languageMap: PlatformConfig = {
  web: ["ts"],
  flutter: ["dart"],
  ios: ["java", "m", "swift"],
  android: ["kt", "java"]
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a039627 and e3f75ac.

⛔ Files ignored due to path filters (7)
  • generated/Destinations.dart is excluded by !**/generated/**
  • generated/Destinations.java is excluded by !**/generated/**
  • generated/Destinations.kt is excluded by !**/generated/**
  • generated/Destinations.m is excluded by !**/generated/**
  • generated/Destinations.swift is excluded by !**/generated/**
  • generated/Destinations.ts is excluded by !**/generated/**
  • generated/destinations.ts is excluded by !**/generated/**
📒 Files selected for processing (9)
  • package.json (2 hunks)
  • scripts/generateConstants.js (1 hunks)
  • templates/Destinations.dart.template (1 hunks)
  • templates/Destinations.java.template (1 hunks)
  • templates/Destinations.kt.template (1 hunks)
  • templates/Destinations.m.template (1 hunks)
  • templates/Destinations.swift.template (1 hunks)
  • templates/Destinations.ts.template (1 hunks)
  • templates/destinations.ts.template (1 hunks)
✅ Files skipped from review due to trivial changes (7)
  • templates/Destinations.dart.template
  • templates/Destinations.java.template
  • templates/Destinations.kt.template
  • templates/Destinations.m.template
  • templates/Destinations.swift.template
  • templates/Destinations.ts.template
  • templates/destinations.ts.template
🧰 Additional context used
🪛 eslint
scripts/generateConstants.js

[error] 1-1: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

🔇 Additional comments (2)
package.json (2)

41-41: LGTM: Valid JSON syntax maintained

The added comma is syntactically correct and maintains valid JSON structure.


42-42: Verify the generate:constants script file

The script addition aligns with the PR objectives for generating destination constants.

Let's verify the script file exists and check its basic structure:

✅ Verification successful

Let me gather more information about the destinations directory and templates to ensure completeness of the verification.


Let me check the content of one of the template files to verify the template structure and its relationship with the destinations.


Based on the comprehensive verification results, I can now provide the final response:

✓ The generateConstants script is properly structured and functional

The script is well-implemented with:

  • Correct directory structure (templates, generated, destinations)
  • Proper template processing logic that reads from src/configurations/destinations
  • Generation of constants for multiple languages (TS, Java, Swift, Dart, etc.)
  • Safe file operations with proper error handling

The script successfully:

  1. Reads destination configurations from db-config.json files
  2. Filters destinations based on language support
  3. Processes templates to generate language-specific constants
  4. Outputs files to the generated directory
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the generateConstants.js script exists and contains expected content

# Check if the script file exists
if [ -f "scripts/generateConstants.js" ]; then
  echo "✓ Script file exists"
  
  # Check if it contains basic template processing logic
  rg -A 5 "template" "scripts/generateConstants.js"
else
  echo "✗ Script file not found at scripts/generateConstants.js"
fi

Length of output: 2329


Script:

#!/bin/bash
# Check the existence and structure of related directories and files

# Check templates directory
echo "=== Templates Directory ==="
if [ -d "templates" ]; then
  echo "✓ Templates directory exists"
  echo "Template files:"
  ls -la templates/
fi

# Check generated directory
echo -e "\n=== Generated Directory ==="
if [ -d "generated" ]; then
  echo "✓ Generated directory exists"
  echo "Generated files:"
  ls -la generated/
fi

# Check destinations directory
echo -e "\n=== Destinations Directory ==="
if [ -d "src/configurations/destinations" ]; then
  echo "✓ Destinations directory exists"
  echo "Destination files:"
  ls -la src/configurations/destinations/
fi

# Check for any existing template files
echo -e "\n=== Template Files ==="
fd -e template

Length of output: 16668


Script:

#!/bin/bash
# Check template content and structure

# Check a template file content
echo "=== Template Content Example ==="
cat templates/Destinations.ts.template

# Check if the script processes all destination directories
echo -e "\n=== Script Processing Check ==="
rg -A 5 "destinations" scripts/generateConstants.js

Length of output: 2031

scripts/generateConstants.js Outdated Show resolved Hide resolved
scripts/generateConstants.js Outdated Show resolved Hide resolved
scripts/generateConstants.js Outdated Show resolved Hide resolved
scripts/generateConstants.js Outdated Show resolved Hide resolved
scripts/generateConstants.js 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 (2)
scripts/generateConstants.js (2)

52-60: Use regex for more robust filename parsing

Consider using a regex pattern for more reliable filename parsing.

 function getLangCode(templateFileName) {
-    const parts = templateFileName.split('.');
-    if (parts.length === 3) {
-        return parts[1];
-    }
-    throw new Error(`Invalid template file name: ${templateFileName}`);
+    const match = templateFileName.match(/^[^.]+\.([^.]+)\.template$/);
+    if (!match) {
+        throw new Error(
+            `Invalid template filename: ${templateFileName}. ` +
+            'Expected format: <template-name>.<lang-code>.template'
+        );
+    }
+    return match[1];
 }

62-90: Add basic error handling for critical file operations

While internal files are trusted, basic error handling for critical file operations would improve reliability.

 function generateFiles() {
+    try {
         // Ensure the 'generated' directory exists
         if (!fs.existsSync(generatedDir)) {
             fs.mkdirSync(generatedDir);
         }
         // Read all files in the templates directory
         fs.readdirSync(templatesDir)
             .filter((file) => file.endsWith('.template'))
             .forEach((file) => {
+                try {
                     const filePath = path.join(templatesDir, file);
                     const destinations = prepareDestinations(getLangCode(file));
                     const templateContent = fs.readFileSync(filePath, 'utf8');
                     const output = processTemplate(templateContent, destinations);
                     const outputFilePath = path.join(generatedDir, file.replace('.template', ''));
                     fs.writeFileSync(outputFilePath, output);
                     console.log(`Generated: ${outputFilePath}`);
+                } catch (error) {
+                    console.error(`Failed to generate ${file}: ${error.message}`);
+                }
             });
+    } catch (error) {
+        console.error(`Generation failed: ${error.message}`);
+        process.exit(1);
+    }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e3f75ac and 3c13954.

📒 Files selected for processing (1)
  • scripts/generateConstants.js (1 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/generateConstants.js (2)
Learnt from: koladilip
PR: rudderlabs/rudder-integrations-config#1800
File: scripts/generateConstants.js:51-60
Timestamp: 2024-11-18T15:30:16.794Z
Learning: In internal Node.js scripts like `scripts/generateConstants.js`, where file validity is assured, additional error handling and async operations are not required.
Learnt from: koladilip
PR: rudderlabs/rudder-integrations-config#1800
File: scripts/generateConstants.js:39-44
Timestamp: 2024-11-18T15:29:10.961Z
Learning: In `scripts/generateConstants.js`, the `processTemplate` function uses `new Function()` but since the template is not taking input from outside, it's acceptable to use `new Function()` in this context.
🪛 eslint
scripts/generateConstants.js

[error] 1-1: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

🔇 Additional comments (4)
scripts/generateConstants.js (4)

1-8: LGTM! Path setup follows Node.js best practices

The path construction using __dirname ensures reliable file resolution regardless of the working directory.

🧰 Tools
🪛 eslint

[error] 1-1: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


34-39: LGTM! Template processing is appropriate for internal use

The use of new Function() is acceptable here as the templates are internal and not user-provided.


41-50: LGTM! Destination preparation is straightforward

The function efficiently processes destination configurations and extracts required properties.


92-93: LGTM! Script execution is straightforward

scripts/generateConstants.js Outdated Show resolved Hide resolved
scripts/generateConstants.js Outdated Show resolved Hide resolved
krishna2020
krishna2020 previously approved these changes Nov 18, 2024
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

🧹 Outside diff range and nitpick comments (3)
scripts/generateConstants.js (3)

47-56: Add type validation for destination properties

While error handling isn't required for internal files, adding type validation would make the code more robust.

Consider adding type checks:

 function prepareDestinations(langCode) {
     return fs.readdirSync(destinationsDir)
         .map((destination) => {
             const destinationsFilePath = path.join(destinationsDir, destination, "db-config.json");
             const destinationsContent = fs.readFileSync(destinationsFilePath, 'utf8');
-            return JSON.parse(destinationsContent);
+            const config = JSON.parse(destinationsContent);
+            if (typeof config.name !== 'string' || typeof config.displayName !== 'string') {
+                console.warn(`Destination ${destination} has invalid name or displayName`);
+                return null;
+            }
+            return config;
         })
+        .filter(Boolean)
         .filter((destination) => filterLanguages(destination, langCode))
         .map((destination) => ({ name: destination.name, displayName: destination.displayName }));
 }

58-67: Use regex for more robust filename validation

The current string splitting approach could be made more robust using regex validation.

Consider using regex for validation:

 function getLangCode(templateFileName) {
-    const parts = templateFileName.split('.');
-    if (parts.length === 3) {
-        return parts[1];
-    }
-    throw new Error(`Invalid template file name: ${templateFileName}`);
+    const match = templateFileName.match(/^[^.]+\.([^.]+)\.template$/);
+    if (!match) {
+        throw new Error(
+            `Invalid template filename: ${templateFileName}. ` +
+            'Expected format: <template-name>.<lang-code>.template'
+        );
+    }
+    return match[1];
 }

69-96: Add summary logging for better monitoring

Consider adding summary logging to track the overall generation process.

Add summary logging:

 function generateFiles() {
+    const results = { total: 0, success: 0, skipped: 0 };
     if (!fs.existsSync(generatedDir)) {
         fs.mkdirSync(generatedDir);
     }
     fs.readdirSync(templatesDir)
         .filter((file) => file.endsWith('.template'))
         .forEach((file) => {
+            results.total++;
             const filePath = path.join(templatesDir, file);
             const destinations = prepareDestinations(getLangCode(file));
+            if (destinations.length === 0) {
+                console.log(`Skipped ${file}: No matching destinations`);
+                results.skipped++;
+                return;
+            }
             const templateContent = fs.readFileSync(filePath, 'utf8');
             const output = processTemplate(templateContent, destinations);
             const outputFilePath = path.join(generatedDir, file.replace('.template', ''));
             fs.writeFileSync(outputFilePath, output);
             console.log(`Generated: ${outputFilePath}`);
+            results.success++;
         });
+    console.log(`Generation complete: ${results.success}/${results.total} files generated, ${results.skipped} skipped`);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3c13954 and d99cee9.

📒 Files selected for processing (1)
  • scripts/generateConstants.js (1 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/generateConstants.js (2)
Learnt from: koladilip
PR: rudderlabs/rudder-integrations-config#1800
File: scripts/generateConstants.js:51-60
Timestamp: 2024-11-18T15:30:16.794Z
Learning: In internal Node.js scripts like `scripts/generateConstants.js`, where file validity is assured, additional error handling and async operations are not required.
Learnt from: koladilip
PR: rudderlabs/rudder-integrations-config#1800
File: scripts/generateConstants.js:39-44
Timestamp: 2024-11-18T15:29:10.961Z
Learning: In `scripts/generateConstants.js`, the `processTemplate` function uses `new Function()` but since the template is not taking input from outside, it's acceptable to use `new Function()` in this context.
🪛 eslint
scripts/generateConstants.js

[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

🔇 Additional comments (2)
scripts/generateConstants.js (2)

17-37: LGTM! Well-structured filtering logic

The function correctly:

  • Validates required fields with appropriate warning logs
  • Filters destinations based on connection modes
  • Checks platform language support

40-45: LGTM! Template processing is appropriate for internal use

The implementation using new Function() is acceptable here as the templates are internal and not user-provided.

scripts/generateConstants.js 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: 0

🧹 Outside diff range and nitpick comments (3)
scripts/generateConstants.js (3)

1-9: Consider migrating to TypeScript for better type safety

The script could benefit from TypeScript's type safety and modern ES module syntax. This would help catch potential errors early and improve maintainability.

Example migration:

import * as fs from 'fs';
import * as path from 'path';

// Define types for better maintainability
interface PathConfig {
  templatesDir: string;
  generatedDir: string;
  destinationsDir: string;
}

const paths: PathConfig = {
  templatesDir: path.join(__dirname, '../templates'),
  generatedDir: path.join(__dirname, '../generated'),
  destinationsDir: path.join(__dirname, '../src/configurations/destinations'),
};
🧰 Tools
🪛 eslint

[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


42-52: Add basic error handling for file operations

While these are internal files, basic error handling would help diagnose issues during development.

 function prepareDestinations(langCode) {
+  try {
     return fs
       .readdirSync(destinationsDir)
       .map((destination) => {
         const destinationsFilePath = path.join(destinationsDir, destination, 'db-config.json');
         const destinationsContent = fs.readFileSync(destinationsFilePath, 'utf8');
         return JSON.parse(destinationsContent);
       })
       .filter((destination) => filterLanguages(destination, langCode))
       .map((destination) => ({ name: destination.name, displayName: destination.displayName }));
+  } catch (error) {
+    console.error(`Error preparing destinations: ${error.message}`);
+    process.exit(1);
+  }
 }

65-91: Add error handling for file operations in generateFiles

The function should handle potential file operation errors gracefully.

 function generateFiles() {
+  try {
     // Ensure the 'generated' directory exists
     if (!fs.existsSync(generatedDir)) {
       fs.mkdirSync(generatedDir);
     }
     
     fs.readdirSync(templatesDir)
       .filter((file) => file.endsWith('.template'))
       .forEach((file) => {
+        try {
           const filePath = path.join(templatesDir, file);
           const destinations = prepareDestinations(getLangCode(file));
           const templateContent = fs.readFileSync(filePath, 'utf8');
           const output = processTemplate(templateContent, destinations);
           const outputFilePath = path.join(generatedDir, file.replace('.template', ''));
           fs.writeFileSync(outputFilePath, output);
           console.log(`Generated: ${outputFilePath}`);
+        } catch (error) {
+          console.error(`Error processing ${file}: ${error.message}`);
+        }
       });
+  } catch (error) {
+    console.error(`Generation failed: ${error.message}`);
+    process.exit(1);
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d99cee9 and 1f9e040.

⛔ Files ignored due to path filters (1)
  • generated/Destinations.ts is excluded by !**/generated/**
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • scripts/generateConstants.js (1 hunks)
  • templates/Destinations.ts.template (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • templates/Destinations.ts.template
🧰 Additional context used
🪛 eslint
scripts/generateConstants.js

[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

🔇 Additional comments (1)
scripts/generateConstants.js (1)

17-33: LGTM! Well-structured filtering logic with proper error handling

The function correctly:

  • Checks for missing supportedConnectionModes with appropriate logging
  • Filters based on device/hybrid mode support
  • Maps platforms to supported languages

saikumarrs
saikumarrs previously approved these changes Nov 19, 2024
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 and nitpick comments (7)
templates/Destinations.kt.template (2)

1-7: Fix typo and clarify file reference in header comment

  1. Line 6: "Containly" should be "Contains"
  2. Line 4: The URL reference might be confusing as it points to the generated file while this is the template file
- NOTE: Containly only constants for device mode destinations
+ NOTE: Contains only constants for device mode destinations

1-14: Consider enhancing the template generation system

To improve the robustness and maintainability of the constants generation system, consider:

  1. Adding TypeScript interfaces for the destination data structure
  2. Implementing a validation step for the generated code (e.g., using a Kotlin parser)
  3. Using a template engine that supports proper code formatting
  4. Adding unit tests for the template generation process

This would help catch errors early and ensure consistent output across all language templates.

scripts/generateConstants.js (5)

1-9: Consider migrating to ES modules

The script currently uses CommonJS require statements. While this works, migrating to ES modules would align with modern JavaScript practices and enable better TypeScript integration.

-const fs = require('fs');
-const path = require('path');
+import * as fs from 'fs';
+import * as path from 'path';
🧰 Tools
🪛 eslint

[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


42-52: Add type validation for destination properties

While error handling isn't required for internal files, adding type validation would make the code more robust.

 .map((destination) => {
+  if (typeof destination.name !== 'string' || typeof destination.displayName !== 'string') {
+    console.warn(`Destination ${destination.name} has invalid name or displayName`);
+    return null;
+  }
   return { name: destination.name, displayName: destination.displayName };
-});
+})
+.filter(Boolean);

54-62: Enhance filename validation with regex

The current string splitting approach could be made more robust with a regex pattern.

 function getLangCode(templateFileName) {
-  const parts = templateFileName.split('.');
-  if (parts.length === 3) {
-    return parts[1];
-  }
-  throw new Error(`Invalid template file name: ${templateFileName}`);
+  const match = templateFileName.match(/^[^.]+\.([^.]+)\.template$/);
+  if (!match) {
+    throw new Error(
+      `Invalid template filename: ${templateFileName}. ` +
+      'Expected format: <template-name>.<lang-code>.template'
+    );
+  }
+  return match[1];
 }

64-91: Add generation statistics

Consider tracking and reporting generation statistics for better visibility.

 function generateFiles() {
+  const stats = { total: 0, success: 0, skipped: 0 };
   if (!fs.existsSync(generatedDir)) {
     fs.mkdirSync(generatedDir);
   }
-  fs.readdirSync(templatesDir)
+  const templates = fs.readdirSync(templatesDir)
     .filter((file) => file.endsWith('.template'))
-    .forEach((file) => {
+  stats.total = templates.length;
+  
+  templates.forEach((file) => {
       const filePath = path.join(templatesDir, file);
       const destinations = prepareDestinations(getLangCode(file));
+      
+      if (destinations.length === 0) {
+        console.log(`Skipped: ${file} (no matching destinations)`);
+        stats.skipped++;
+        return;
+      }
 
       const templateContent = fs.readFileSync(filePath, 'utf8');
       const output = processTemplate(templateContent, destinations);
       const outputFilePath = path.join(generatedDir, file.replace('.template', ''));
       fs.writeFileSync(outputFilePath, output);
       console.log(`Generated: ${outputFilePath}`);
+      stats.success++;
     });
+  console.log(`\nGeneration complete: ${stats.success}/${stats.total} files generated, ${stats.skipped} skipped`);
 }

93-94: Add proper exit code handling

Consider adding proper exit code handling for better integration with build tools.

-// Generate the files
-generateFiles();
+try {
+  generateFiles();
+  process.exit(0);
+} catch (error) {
+  console.error('Generation failed:', error);
+  process.exit(1);
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1f9e040 and 5706742.

⛔ Files ignored due to path filters (1)
  • generated/Destinations.ts is excluded by !**/generated/**
📒 Files selected for processing (7)
  • scripts/generateConstants.js (1 hunks)
  • templates/Destinations.dart.template (1 hunks)
  • templates/Destinations.java.template (1 hunks)
  • templates/Destinations.kt.template (1 hunks)
  • templates/Destinations.m.template (1 hunks)
  • templates/Destinations.swift.template (1 hunks)
  • templates/Destinations.ts.template (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • templates/Destinations.dart.template
  • templates/Destinations.java.template
  • templates/Destinations.m.template
  • templates/Destinations.swift.template
  • templates/Destinations.ts.template
🧰 Additional context used
🪛 eslint
scripts/generateConstants.js

[error] 2-2: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)


[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

🔇 Additional comments (3)
templates/Destinations.kt.template (1)

9-14: Enhance template robustness and formatting

The template could benefit from additional safety measures and formatting improvements:

  1. Consider adding null/undefined checks for dest.name and dest.displayName
  2. Add validation for special characters in displayName that might need escaping
  3. Ensure consistent formatting in the generated code

Consider updating the template to include validation and proper formatting:

 object Destinations {
-  ${destinations.map((dest) => `
-  const val ${dest.name}_NAME = "${dest.name}"
-
-  const val ${dest.name}_DISPLAY_NAME = "${dest.displayName}"`).join('\n')}
+  ${destinations.map((dest) => {
+    if (!dest.name || !dest.displayName) {
+      throw new Error(`Invalid destination: ${JSON.stringify(dest)}`);
+    }
+    const escapedDisplayName = dest.displayName.replace(/"/g, '\\"');
+    return `
+    const val ${dest.name}_NAME = "${dest.name}"
+    const val ${dest.name}_DISPLAY_NAME = "${escapedDisplayName}"
+    `;
+  }).join('\n').trim()}
 }

Let's verify the destinations data structure:

scripts/generateConstants.js (2)

10-15: LGTM! Language mapping is accurate

The platform-to-language mapping correctly represents the supported languages for each platform.


17-33: LGTM! Filtering logic with proper error handling

The function correctly filters destinations based on connection modes and includes the requested logging for missing configurations.

krishna2020
krishna2020 previously approved these changes Nov 19, 2024
@koladilip koladilip merged commit 5f58915 into develop Nov 19, 2024
11 checks passed
@koladilip koladilip deleted the feat/generate-destination-constants branch November 19, 2024 07:39
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.

4 participants