feat: implement code review improvements for flexible instance configuration

- Add cache-utils.ts with hash memoization, configurable cache, metrics tracking, mutex, and retry logic
- Enhance validation with field-specific error messages in instance-context.ts
- Add JSDoc documentation to all public methods
- Make cache configurable via INSTANCE_CACHE_MAX and INSTANCE_CACHE_TTL_MINUTES env vars
- Add comprehensive test coverage for cache utilities and metrics monitoring
- Fix test expectations for new validation error format

Addresses all feedback from PR #209 code review

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-09-19 22:26:04 +02:00
parent b366d40d67
commit 34c7f756e1
8 changed files with 1543 additions and 67 deletions

View File

@@ -22,7 +22,8 @@ describe('instance-context Coverage Tests', () => {
const result = validateInstanceContext(context);
expect(result.valid).toBe(false);
expect(result.errors).toContain('Invalid n8nApiUrl format');
expect(result.errors?.[0]).toContain('Invalid n8nApiUrl:');
expect(result.errors?.[0]).toContain('empty string');
});
it('should handle empty string API key validation', () => {
@@ -34,7 +35,8 @@ describe('instance-context Coverage Tests', () => {
const result = validateInstanceContext(context);
expect(result.valid).toBe(false);
expect(result.errors).toContain('Invalid n8nApiKey format');
expect(result.errors?.[0]).toContain('Invalid n8nApiKey:');
expect(result.errors?.[0]).toContain('empty string');
});
it('should handle Infinity values for timeout', () => {
@@ -47,7 +49,8 @@ describe('instance-context Coverage Tests', () => {
const result = validateInstanceContext(context);
expect(result.valid).toBe(false);
expect(result.errors).toContain('n8nApiTimeout must be a positive number');
expect(result.errors?.[0]).toContain('Invalid n8nApiTimeout:');
expect(result.errors?.[0]).toContain('Must be a finite number');
});
it('should handle -Infinity values for timeout', () => {
@@ -60,7 +63,8 @@ describe('instance-context Coverage Tests', () => {
const result = validateInstanceContext(context);
expect(result.valid).toBe(false);
expect(result.errors).toContain('n8nApiTimeout must be a positive number');
expect(result.errors?.[0]).toContain('Invalid n8nApiTimeout:');
expect(result.errors?.[0]).toContain('Must be positive');
});
it('should handle Infinity values for retries', () => {
@@ -73,7 +77,8 @@ describe('instance-context Coverage Tests', () => {
const result = validateInstanceContext(context);
expect(result.valid).toBe(false);
expect(result.errors).toContain('n8nApiMaxRetries must be a non-negative number');
expect(result.errors?.[0]).toContain('Invalid n8nApiMaxRetries:');
expect(result.errors?.[0]).toContain('Must be a finite number');
});
it('should handle -Infinity values for retries', () => {
@@ -86,7 +91,8 @@ describe('instance-context Coverage Tests', () => {
const result = validateInstanceContext(context);
expect(result.valid).toBe(false);
expect(result.errors).toContain('n8nApiMaxRetries must be a non-negative number');
expect(result.errors?.[0]).toContain('Invalid n8nApiMaxRetries:');
expect(result.errors?.[0]).toContain('Must be non-negative');
});
it('should handle multiple validation errors at once', () => {
@@ -101,10 +107,10 @@ describe('instance-context Coverage Tests', () => {
expect(result.valid).toBe(false);
expect(result.errors).toHaveLength(4);
expect(result.errors).toContain('Invalid n8nApiUrl format');
expect(result.errors).toContain('Invalid n8nApiKey format');
expect(result.errors).toContain('n8nApiTimeout must be a positive number');
expect(result.errors).toContain('n8nApiMaxRetries must be a non-negative number');
expect(result.errors?.some(err => err.includes('Invalid n8nApiUrl:'))).toBe(true);
expect(result.errors?.some(err => err.includes('Invalid n8nApiKey:'))).toBe(true);
expect(result.errors?.some(err => err.includes('Invalid n8nApiTimeout:'))).toBe(true);
expect(result.errors?.some(err => err.includes('Invalid n8nApiMaxRetries:'))).toBe(true);
});
it('should return no errors property when validation passes', () => {
@@ -288,7 +294,15 @@ describe('instance-context Coverage Tests', () => {
const validation = validateInstanceContext(context);
expect(validation.valid).toBe(false);
expect(validation.errors).toContain('Invalid n8nApiKey format');
// Check for any of the specific error messages
const hasValidError = validation.errors?.some(err =>
err.includes('Invalid n8nApiKey:') && (
err.includes('placeholder') ||
err.includes('example') ||
err.includes('your_api_key')
)
);
expect(hasValidError).toBe(true);
});
});