Skip to content

Conversation

narengogi
Copy link
Collaborator

@narengogi narengogi commented Aug 11, 2025

Changes included in this PR:

  • utility for fetching environment variables
  • Bedrock/AWS proxy routes support

Changes not included:
Support for IRSA and IMDS based auth

Copy link
Contributor

matter-code-review bot commented Aug 11, 2025

Code Quality bug fix refactoring

Description

Summary By MatterAI MatterAI logo

🔄 What Changed

This pull request modifies src/utils/env.ts to dynamically import the path module. The import now occurs conditionally, only when the application is running in a Node.js environment, determined by getRuntimeKey() == 'node'. This change replaces a static import of path.

🔍 Impact of the Change

This change significantly improves the cross-runtime compatibility of the utility functions, particularly for environments like Cloudflare Workers where the Node.js path module is not available. By conditionally importing, it prevents runtime errors in non-Node.js environments, making the codebase more robust and portable without affecting Node.js execution.

📁 Total Files Changed

  • src/utils/env.ts: Dynamically imports the path module based on the runtime environment to ensure compatibility across Node.js and other platforms.

🧪 Test Added

N/A

🔒Security Vulnerabilities

N/A

Motivation

This PR addresses runtime compatibility issues by ensuring that Node.js-specific modules like path are only loaded when the application is executing in a Node.js environment. This is crucial for supporting diverse deployment targets, such as serverless functions or edge runtimes, where Node.js built-in modules might not be present.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)

How Has This Been Tested?

  • Unit Tests
  • Integration Tests
  • Manual Testing

Screenshots (if applicable)

N/A

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Related Issues

N/A

Tip

Quality Recommendations

  1. Consider adding unit tests to verify the conditional import of the path module, ensuring it's correctly loaded in Node.js environments and not attempted in non-Node.js environments (e.g., by mocking getRuntimeKey).

Tanka Poem ♫

Runtime shifts, a new path,
Node's module, now conditional.
Code adapts, flows free,
No more errors, cross-platform glee.
Logic's elegant design. ✨

Sequence Diagram

sequenceDiagram
    participant EnvUtil as src/utils/env.ts
    participant HonoAdapter as hono/adapter
    participant NodeRuntime as Node.js Runtime
    participant OtherRuntime as Other Runtime (e.g., Workers)

    EnvUtil->>HonoAdapter: getRuntimeKey()
    alt Runtime is 'node'
        HonoAdapter-->>EnvUtil: 'node'
        EnvUtil->>+NodeRuntime: import('path')
        NodeRuntime-->>-EnvUtil: path module
    else Runtime is not 'node'
        HonoAdapter-->>EnvUtil: 'workerd' (or other)
        Note over EnvUtil: 'path' remains undefined
    end
Loading

Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Code review completed. Found several areas for improvement including missing error handling, potential security issues, and documentation gaps.

Comment on lines +8 to +35
export function getValueOrFileContents(value?: string, ignore?: boolean) {
if (!value || ignore) return value;

try {
// Check if value looks like a file path
if (
value.startsWith('/') ||
value.startsWith('./') ||
value.startsWith('../')
) {
// Resolve the path (handle relative paths)
const resolvedPath = path.resolve(value);

// Check if file exists
if (fs.existsSync(resolvedPath)) {
// File exists, read and return its contents
return fs.readFileSync(resolvedPath, 'utf8').trim();
}
}

// If not a file path or file doesn't exist, return value as is
return value;
} catch (error: any) {
console.log(`Error reading file at ${value}: ${error.message}`);
// Return the original value if there's an error
return value;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🔒 Security Issue Fix

Issue: Path traversal vulnerability - the function accepts any file path without validation, potentially allowing access to sensitive files outside intended directories
Fix: Add path validation to restrict file access to safe directories
Impact: Prevents potential security breach through malicious file path injection

Suggested change
export function getValueOrFileContents(value?: string, ignore?: boolean) {
if (!value || ignore) return value;
try {
// Check if value looks like a file path
if (
value.startsWith('/') ||
value.startsWith('./') ||
value.startsWith('../')
) {
// Resolve the path (handle relative paths)
const resolvedPath = path.resolve(value);
// Check if file exists
if (fs.existsSync(resolvedPath)) {
// File exists, read and return its contents
return fs.readFileSync(resolvedPath, 'utf8').trim();
}
}
// If not a file path or file doesn't exist, return value as is
return value;
} catch (error: any) {
console.log(`Error reading file at ${value}: ${error.message}`);
// Return the original value if there's an error
return value;
}
}
export function getValueOrFileContents(value?: string, ignore?: boolean) {
if (!value || ignore) return value;
try {
// Check if value looks like a file path
if (
value.startsWith('/') ||
value.startsWith('./') ||
value.startsWith('../')
) {
// Resolve the path (handle relative paths)
const resolvedPath = path.resolve(value);
// Security: Validate path is within allowed directories
const allowedPaths = [process.cwd(), '/etc/ssl/certs', '/var/secrets'];
const isPathAllowed = allowedPaths.some(allowedPath =>
resolvedPath.startsWith(path.resolve(allowedPath))
);
if (!isPathAllowed) {
console.warn(`Access denied to path outside allowed directories: ${resolvedPath}`);
return value;
}
// Check if file exists
if (fs.existsSync(resolvedPath)) {
// File exists, read and return its contents
return fs.readFileSync(resolvedPath, 'utf8').trim();
}
}
// If not a file path or file doesn't exist, return value as is
return value;
} catch (error: any) {
console.log(`Error reading file at ${value}: ${error.message}`);
// Return the original value if there's an error
return value;
}
}

Comment on lines +126 to +127
const model = params.foundationModel || params.model || '';
if (g1EmbedModels.includes(model)) return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Potential null/undefined access - params.foundationModel and params.model could be undefined, causing the includes() check to fail
Fix: Add proper null/undefined checks before accessing model properties
Impact: Prevents runtime errors when model parameters are missing

Suggested change
const model = params.foundationModel || params.model || '';
if (g1EmbedModels.includes(model)) return undefined;
const model = params?.foundationModel || params?.model || '';
if (model && g1EmbedModels.includes(model)) return undefined;

Comment on lines 39 to 46
headers: async ({ providerOptions, fn }) => {
const {
apiKey,
azureExtraParams,
azureExtraParameters,
azureDeploymentName,
azureAdToken,
azureAuthMode,
} = providerOptions;
Copy link
Contributor

Choose a reason for hiding this comment

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

📝 Documentation Gap

Issue: Missing JSDoc documentation for the azureExtraParameters field and its purpose
Fix: Add comprehensive documentation explaining the parameter's usage
Impact: Improves code maintainability and developer understanding

Suggested change
headers: async ({ providerOptions, fn }) => {
const {
apiKey,
azureExtraParams,
azureExtraParameters,
azureDeploymentName,
azureAdToken,
azureAuthMode,
} = providerOptions;
headers: async ({ providerOptions, fn }) => {
const {
apiKey,
/**
* Azure extra parameters configuration
* Controls how extra parameters are handled in the request
* @default 'drop' - drops extra parameters not supported by the model
*/
azureExtraParameters,
azureDeploymentName,
azureAdToken,
azureAuthMode,
} = providerOptions;

Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use Matter AI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with Matter AI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

@narengogi narengogi marked this pull request as ready for review August 12, 2025 09:16
@narengogi narengogi requested review from roh26it and VisargD August 12, 2025 09:16
@narengogi narengogi changed the title Chore/bedrock cleanup bedrock provider cleanup Aug 12, 2025
@narengogi narengogi force-pushed the chore/bedrock-cleanup branch from bc360ce to 7a18e60 Compare September 1, 2025 14:04
Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Bedrock provider cleanup with proxy support and AWS endpoint domain improvements. Found critical null safety issues and missing error handling.

Comment on lines +70 to +77
const getMethod = (
fn: endpointStrings,
transformedRequestUrl: string,
c: Context
) => {
if (fn === 'proxy') {
return c.req.method;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Missing null/undefined check for Context parameter - if c is null/undefined, accessing c.req.method will throw a runtime error
Fix: Add null check before accessing Context properties
Impact: Prevents runtime crashes when Context is not properly initialized

Suggested change
const getMethod = (
fn: endpointStrings,
transformedRequestUrl: string,
c: Context
) => {
if (fn === 'proxy') {
return c.req.method;
}
const getMethod = (
fn: endpointStrings,
transformedRequestUrl: string,
c: Context
) => {
if (fn === 'proxy') {
return c?.req?.method || 'GET';
}

Comment on lines +31 to +32
finalizing_at: new Date(batch.endTime).getTime(),
expires_at: new Date(batch.jobExpirationTime).getTime(),
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Removed null checks for Date constructor - if batch.endTime or batch.jobExpirationTime are null/undefined, new Date(null) returns invalid date and getTime() returns NaN
Fix: Restore null checks to handle missing timestamps safely
Impact: Prevents NaN values in API responses which could break client applications

Suggested change
finalizing_at: new Date(batch.endTime).getTime(),
expires_at: new Date(batch.jobExpirationTime).getTime(),
finalizing_at: batch.endTime
? new Date(batch.endTime).getTime()
: undefined,
expires_at: batch.jobExpirationTime
? new Date(batch.jobExpirationTime).getTime()
: undefined,

Comment on lines 880 to +884
usage: {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0,
prompt_tokens: response.usage.input_tokens,
completion_tokens: response.usage.output_tokens,
total_tokens:
response.usage.input_tokens + response.usage.output_tokens,
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Missing null/undefined check for response.usage - if the usage object is missing, accessing response.usage.input_tokens will throw a runtime error
Fix: Add null check before accessing usage properties
Impact: Prevents runtime crashes when usage data is not provided by the API

Suggested change
usage: {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0,
prompt_tokens: response.usage.input_tokens,
completion_tokens: response.usage.output_tokens,
total_tokens:
response.usage.input_tokens + response.usage.output_tokens,
usage: {
prompt_tokens: response.usage?.input_tokens || 0,
completion_tokens: response.usage?.output_tokens || 0,
total_tokens:
(response.usage?.input_tokens || 0) + (response.usage?.output_tokens || 0),
},

Comment on lines +70 to +77
const getMethod = (
fn: endpointStrings,
transformedRequestUrl: string,
c: Context
) => {
if (fn === 'proxy') {
return c.req.method;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Code Refactor

Issue: Inconsistent parameter naming - using 'c' for Context parameter while other functions use more descriptive names
Fix: Use consistent parameter naming for better code readability
Impact: Improves code maintainability and follows established patterns

Suggested change
const getMethod = (
fn: endpointStrings,
transformedRequestUrl: string,
c: Context
) => {
if (fn === 'proxy') {
return c.req.method;
}
const getMethod = (
fn: endpointStrings,
transformedRequestUrl: string,
context: Context
) => {
if (fn === 'proxy') {
return context?.req?.method || 'GET';
}

Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Dynamic import implementation looks correct but has potential type safety and performance issues

Comment on lines +6 to +9
let path: any;
if (isNodeInstance) {
path = await import('path');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Using any type defeats TypeScript's type safety - path module methods won't have proper type checking and IDE support
Fix: Use proper typing for the dynamically imported path module
Impact: Enables type checking and prevents runtime errors from incorrect method usage

Suggested change
let path: any;
if (isNodeInstance) {
path = await import('path');
}
let path: typeof import('path') | undefined;
if (isNodeInstance) {
path = await import('path');
}

Comment on lines +6 to +9
let path: any;
if (isNodeInstance) {
path = await import('path');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚡️ Performance Improvement

Issue: Top-level await in module can block other imports and cause initialization delays
Fix: Move dynamic import to function scope where path is actually used
Impact: Reduces module initialization time and prevents blocking other imports

Suggested change
let path: any;
if (isNodeInstance) {
path = await import('path');
}
let pathModule: typeof import('path') | undefined;
const getPath = async () => {
if (isNodeInstance && !pathModule) {
pathModule = await import('path');
}
return pathModule;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant