UNPKG

meld

Version:

Meld: A template language for LLM prompts

299 lines (232 loc) 9.35 kB
# Meld Utility Infrastructure This document provides an overview of the utility infrastructure available in the Meld codebase for both production and testing environments. ## Production Utilities ### Core Utilities #### Logger (`core/utils/logger.ts`) - Provides structured logging throughout the application - Supports different log levels (debug, info, warn, error) - Service-specific loggers (stateLogger, parserLogger, etc.) - Can be configured for different environments #### Service Validation (`core/utils/serviceValidation.ts`) - Validates service dependency graph - Ensures services are initialized in the correct order - Prevents circular dependencies - Throws `ServiceInitializationError` for invalid configurations ### Error Handling #### MeldError (`core/errors/MeldError.ts`) - Base error class for all Meld-specific errors - Supports error codes and severity levels - Structured error information for better debugging #### Specialized Errors - `MeldDirectiveError`: For directive-specific errors - `MeldParseError`: For parsing errors - `MeldInterpreterError`: For interpretation errors - `MeldResolutionError`: For variable resolution errors - `PathValidationError`: For path validation errors - `ServiceInitializationError`: For service initialization errors ### Path Handling #### PathService (`services/fs/PathService/PathService.ts`) - Validates and normalizes paths - Handles special path variables ($HOMEPATH/$~, $PROJECTPATH/$.) - Handles user-defined path variables ($path) created by @path directives - Resolves path variables in different contexts (directives, imports, etc.) - Supports test mode for path operations - Enforces path security constraints - Validates path structure and segments - Prevents path traversal attacks #### PathOperationsService (`services/fs/FileSystemService/PathOperationsService.ts`) - Handles path joining and manipulation - Normalizes paths across platforms - Provides utility functions for path operations ## Testing Infrastructure ### Test Context #### TestContext (`tests/utils/TestContext.ts`) - Central test harness that provides access to all services - Creates an isolated test environment for each test - Provides methods for: - File operations (`writeFile`, `readFile`, etc.) - Path resolution (`resolveSpecialPath`) - Service management (`enableTransformation`, `disableTransformation`, etc.) - Environment variable management (`withEnvironment`) - CLI testing (`setupCliTest`) - Debug session management (`startDebugSession`, `endDebugSession`) - State visualization (`visualizeState`) ### File System Mocking #### MemfsTestFileSystem (`tests/utils/MemfsTestFileSystem.ts`) - In-memory file system for testing - Implements the `IFileSystem` interface - Provides methods for file operations (read, write, mkdir, etc.) - Supports watching for file changes - Initializes with a standard directory structure #### MemfsTestFileSystemAdapter (`tests/utils/MemfsTestFileSystemAdapter.ts`) - Adapts `MemfsTestFileSystem` for use with CLI tests - Provides a consistent interface for file operations - Handles path resolution for CLI contexts ### CLI Testing #### cliTestHelper (`tests/utils/cli/cliTestHelper.ts`) - Sets up a complete CLI test environment - Provides methods for: - Creating test files - Setting environment variables - Mocking process.exit - Mocking console output - Verifying CLI behavior #### mockProcessExit (`tests/utils/cli/mockProcessExit.ts`) - Mocks `process.exit` for testing CLI exit behavior - Captures exit codes for verification - Prevents tests from actually exiting #### mockConsole (`tests/utils/cli/mockConsole.ts`) - Mocks console methods (log, error, warn, info) - Captures console output for verification - Supports testing CLI output formatting ### Test Data Management #### ProjectBuilder (`tests/utils/ProjectBuilder.ts`) - Creates mock "projects" in the in-memory file system - Supports creating complex directory structures - Useful for testing imports and path resolution #### TestSnapshot (`tests/utils/TestSnapshot.ts`) - Takes "snapshots" of the in-memory file system - Compares snapshots to detect changes - Useful for verifying file operations #### FixtureManager (`tests/utils/FixtureManager.ts`) - Loads test fixtures from JSON files - Provides access to test data - Supports creating complex test scenarios ### Node Factories #### nodeFactories (`tests/utils/nodeFactories.ts`) - Creates AST nodes for testing - Supports creating directive, text, and code fence nodes - Provides location information for source mapping #### testFactories (`tests/utils/testFactories.ts`) - Creates test data for various services - Supports creating complex test scenarios - Provides factory functions for common test patterns ### Debug Utilities #### StateDebuggerService (`tests/utils/debug/StateDebuggerService/StateDebuggerService.ts`) - Provides debug session management - Captures state operations and transformations - Generates debug reports - Supports visualization of state changes #### StateTrackingService (`tests/utils/debug/StateTrackingService/StateTrackingService.ts`) - Tracks state relationships and dependencies - Records metadata about state changes - Helps debug scope and inheritance issues #### StateVisualizationService (`tests/utils/debug/StateVisualizationService/StateVisualizationService.ts`) - Generates visual representations of state - Creates Mermaid/DOT graphs of state relationships - Visualizes state metrics and transformations #### StateHistoryService (`tests/utils/debug/StateHistoryService/StateHistoryService.ts`) - Records chronological state changes - Maintains operation history - Enables state change replay and analysis ### Error Testing #### ErrorTestUtils (`tests/utils/ErrorTestUtils.ts`) - Provides utilities for testing error handling - Supports verifying error types and messages - Helps test error recovery scenarios ## Integration Points ### API Integration The API (`api/index.ts`) integrates these utilities through: - Service initialization via `createDefaultServices()` - Service validation via `validateServicePipeline()` - Error handling with proper type preservation - Debug mode support ### Test Integration Tests integrate these utilities through: - `TestContext` for test setup and service access - `MemfsTestFileSystem` for file operations - Debug services for state visualization and tracking - Error utilities for verifying error handling ## Usage Examples ### Setting Up a Basic Test ```typescript import { TestContext } from '@tests/utils/TestContext'; describe('My Test', () => { let context: TestContext; beforeEach(async () => { context = new TestContext(); await context.initialize(); }); afterEach(async () => { await context.cleanup(); }); it('should process a file', async () => { // Write a test file await context.writeFile('/test.meld', '@text greeting = "Hello"'); // Process the file const result = await context.services.interpreter.interpret( context.services.parser.parse('@text greeting = "Hello"') ); // Verify the result expect(context.services.state.getTextVar('greeting')).toBe('Hello'); }); }); ``` ### Setting Up a CLI Test ```typescript import { TestContext } from '@tests/utils/TestContext'; describe('CLI Test', () => { let context: TestContext; beforeEach(async () => { context = new TestContext(); await context.initialize(); }); afterEach(async () => { await context.cleanup(); }); it('should handle CLI arguments', async () => { // Set up CLI test environment const { exitMock, consoleMocks } = await context.setupCliTest({ files: { '/project/test.meld': '@text greeting = "Hello"' }, env: { NODE_ENV: 'test' }, mockExit: true, mockConsoleOutput: true }); // Run CLI command process.argv = ['node', 'meld', '$./test.meld', '--stdout']; await cli.main(); // Verify results expect(exitMock).not.toHaveBeenCalled(); expect(consoleMocks.log).toHaveBeenCalledWith('Hello'); }); }); ``` ### Using Debug Services ```typescript import { TestContext } from '@tests/utils/TestContext'; describe('Debug Test', () => { let context: TestContext; let debugSessionId: string; beforeEach(async () => { context = new TestContext(); await context.initialize(); // Start debug session debugSessionId = await context.startDebugSession({ captureConfig: { capturePoints: ['pre-transform', 'post-transform'], includeFields: ['nodes', 'variables'] } }); }); afterEach(async () => { // End debug session and get results const debugResult = await context.endDebugSession(debugSessionId); console.log('Debug operations:', debugResult.operations); await context.cleanup(); }); it('should track state changes', async () => { // Write and process a test file await context.writeFile('/test.meld', '@text greeting = "Hello"'); await context.services.interpreter.interpret( context.services.parser.parse('@text greeting = "Hello"') ); // Visualize state const visualization = await context.visualizeState(); console.log('State visualization:', visualization); }); }); ```