tests — utils

Module: tests-utils Cohesion: 0.80 Members: 0

tests — utils

This document provides an overview of the core utility modules within the src/utils directory. These modules offer foundational, reusable functionalities that support various aspects of the application, from data management and validation to error handling and user interaction.

The documentation for each utility is derived from its comprehensive test suite, highlighting its purpose, key components, and how its API is intended to be used.


Core Utility Modules

1. Cache (src/utils/cache.ts)

The Cache module provides a simple, in-memory key-value store with optional Time-To-Live (TTL) functionality. It's designed for caching frequently accessed data to improve performance.

Purpose: To store and retrieve data efficiently, with support for automatic expiration and on-demand computation of missing values.

Key Components:

API & Functionality:

Usage Example:

import { Cache, createCacheKey } from './src/utils/cache';

const myCache = new Cache<string>(5000); class="hl-cmt">// Default TTL of 5 seconds

class="hl-cmt">// Basic operations
myCache.set(&#39;user:1&#39;, &#39;Alice&#39;);
console.log(myCache.get(&#39;user:1&#39;)); class="hl-cmt">// &#39;Alice&#39;

class="hl-cmt">// Custom TTL
myCache.set(&#39;temp_data&#39;, &#39;some_value&#39;, 100); class="hl-cmt">// Expires in 100ms

class="hl-cmt">// Asynchronous computation
async function fetchUserData(userId: string) {
  return myCache.getOrCompute(`user_data:${userId}`, async () => {
    console.log(`Fetching data for ${userId}...`);
    await new Promise(resolve => setTimeout(resolve, 100)); class="hl-cmt">// Simulate API call
    return `Data for ${userId}`;
  });
}

(async () => {
  console.log(await fetchUserData(&#39;2&#39;)); class="hl-cmt">// Fetches and caches
  console.log(await fetchUserData(&#39;2&#39;)); class="hl-cmt">// Returns from cache, no computation
})();

class="hl-cmt">// Creating complex keys
const key = createCacheKey(&#39;report&#39;, 2023, &#39;Q4&#39;, true); class="hl-cmt">// "report:2023:Q4:true"

2. Confirmation Service (src/utils/confirmation-service.ts)

The ConfirmationService manages user confirmation states for sensitive operations and provides a dry-run mode for previewing actions without execution.

Purpose: To centralize the logic for user confirmations, manage a dry-run mode, and log actions performed in dry-run. It acts as a single point of control for interactive operations.

Key Components:

API & Functionality:

Usage Example:

import { ConfirmationService } from &#39;./src/utils/confirmation-service&#39;;

const service = ConfirmationService.getInstance();

service.on(&#39;confirmationRequired&#39;, (message, type) => {
  console.log(`Confirmation needed for ${type}: ${message}`);
  class="hl-cmt">// In a real UI, this would prompt the user
  service.confirmOperation(true, true); class="hl-cmt">// Auto-confirm for example
});

service.setDryRunMode(true);
class="hl-cmt">// Simulate an operation that would normally require confirmation
class="hl-cmt">// In dry-run mode, it would log instead of prompting
class="hl-cmt">// service.requestConfirmation(&#39;Delete sensitive file?&#39;, &#39;fileOperations&#39;);
class="hl-cmt">// console.log(service.getDryRunLog());

service.setDryRunMode(false);
service.setSessionFlag(&#39;fileOperations&#39;, true); class="hl-cmt">// User agreed to all file ops
class="hl-cmt">// Now, file operations might proceed without explicit prompt

3. Disposable System (src/utils/disposable.ts)

The Disposable system provides a robust mechanism for managing resources that need explicit cleanup, ensuring they are disposed of correctly, especially in a Last-In, First-Out (LIFO) order.

Purpose: To prevent resource leaks by centralizing the registration and disposal of objects that implement the Disposable interface. It's particularly useful for managing subscriptions, file handles, or other resources that require explicit release.

Key Components:

API & Functionality:

DisposableManager Class:

Global Helper Functions:

Usage Example:

import { registerDisposable, disposeAll, Disposable } from &#39;./src/utils/disposable&#39;;

class MyResource implements Disposable {
  private id: number;
  constructor(id: number) {
    this.id = id;
    console.log(`Resource ${this.id} created.`);
    registerDisposable(this); class="hl-cmt">// Register itself for automatic cleanup
  }

  async dispose() {
    console.log(`Disposing Resource ${this.id}...`);
    await new Promise(resolve => setTimeout(resolve, 10)); class="hl-cmt">// Simulate async cleanup
    console.log(`Resource ${this.id} disposed.`);
  }
}

function setupApplication() {
  new MyResource(1);
  new MyResource(2);
  class="hl-cmt">// ... more resources
}

async function shutdownApplication() {
  console.log(&#39;Shutting down application, disposing resources...&#39;);
  await disposeAll(); class="hl-cmt">// This will call dispose on MyResource(2) then MyResource(1)
  console.log(&#39;Application shutdown complete.&#39;);
}

setupApplication();
shutdownApplication();

4. Error Utilities (src/utils/errors.ts)

This module defines a set of custom error classes for specific application scenarios and provides utility functions for robust error handling, including retries and timeouts for asynchronous operations.

Purpose: To provide a structured and categorized error system, making error identification and handling more consistent. It also offers practical utilities for managing common asynchronous failure patterns.

Key Components:

Custom Error Classes (all extend CodeBuddyError):

Utility Functions:

Usage Example:

import {
  CodeBuddyError,
  APIError,
  FileNotFoundError,
  withTimeout,
  withRetry,
  getErrorMessage,
} from &#39;./src/utils/errors&#39;;

class="hl-cmt">// Custom Error Usage
try {
  throw new APIError(&#39;Failed to fetch user data&#39;, 500, { reason: &#39;server_error&#39; });
} catch (e) {
  if (e instanceof APIError) {
    console.error(`API Error (${e.statusCode}): ${e.message} - Details: ${JSON.stringify(e.response)}`);
  }
}

class="hl-cmt">// withTimeout Usage
async function fetchDataWithTimeout() {
  const slowPromise = new Promise(resolve => setTimeout(() => resolve(&#39;data&#39;), 500));
  try {
    const result = await withTimeout(slowPromise, 100, &#39;Data fetch took too long!&#39;);
    console.log(result);
  } catch (e) {
    console.error(getErrorMessage(e)); class="hl-cmt">// "Data fetch took too long!"
  }
}
fetchDataWithTimeout();

class="hl-cmt">// withRetry Usage
let attemptCount = 0;
async function flakyOperation() {
  attemptCount++;
  console.log(`Attempt ${attemptCount} to perform flaky operation...`);
  if (attemptCount < 3) {
    throw new Error(&#39;Transient network issue&#39;);
  }
  return &#39;Operation successful!&#39;;
}

(async () => {
  try {
    const result = await withRetry(flakyOperation, { maxRetries: 2, initialDelay: 50 });
    console.log(result); class="hl-cmt">// "Operation successful!" after 3 attempts
  } catch (e) {
    console.error(`Failed after retries: ${getErrorMessage(e)}`);
  }
})();

5. Exit Codes (src/utils/exit-codes.ts)

This module defines a standardized set of exit codes for the application and provides utilities to manage the application's exit behavior, including mapping errors to appropriate exit codes.

Purpose: To ensure consistent and meaningful exit codes, allowing external scripts or CI/CD pipelines to interpret the application's termination status reliably. It also centralizes fatal error handling.

Key Components:

API & Functionality:

Usage Example:

import {
  EXIT_CODES,
  exitWithCode,
  errorToExitCode,
  handleFatalError,
} from &#39;./src/utils/exit-codes&#39;;
import { APIError, FileNotFoundError } from &#39;./src/utils/errors&#39;; class="hl-cmt">// Assuming custom errors

function performOperation(shouldFail: boolean, errorType?: string) {
  try {
    if (shouldFail) {
      if (errorType === &#39;api&#39;) {
        throw new APIError(&#39;Service unavailable&#39;, 503);
      } else if (errorType === &#39;file&#39;) {
        throw new FileNotFoundError(&#39;/non/existent/file.txt&#39;);
      } else if (errorType === &#39;auth&#39;) {
        throw new Error(&#39;Invalid API key&#39;); class="hl-cmt">// errorToExitCode will map this
      } else {
        throw new Error(&#39;An unexpected error occurred.&#39;);
      }
    }
    exitWithCode(EXIT_CODES.SUCCESS, &#39;Operation completed successfully.&#39;);
  } catch (e) {
    handleFatalError(e); class="hl-cmt">// This will log the error and exit with the mapped code
  }
}

class="hl-cmt">// Example calls (these would typically terminate the process)
class="hl-cmt">// performOperation(false); // Exits with SUCCESS
class="hl-cmt">// performOperation(true, &#39;api&#39;); // Exits with API_ERROR
class="hl-cmt">// performOperation(true, &#39;file&#39;); // Exits with FILE_NOT_FOUND
class="hl-cmt">// performOperation(true, &#39;auth&#39;); // Exits with AUTHENTICATION_ERROR
class="hl-cmt">// performOperation(true); // Exits with GENERAL_ERROR

6. Glob Matcher (src/utils/glob-matcher.ts)

This module provides utilities for matching strings against glob patterns, commonly used for filtering lists of items like files, tools, or configurations.

Purpose: To offer flexible pattern matching capabilities, similar to shell globs, for filtering and selection logic within the application.

Key Components:

API & Functionality:

Usage Example:

import {
  matchGlob,
  filterByGlob,
  filterTools,
  isToolEnabled,
} from &#39;./src/utils/glob-matcher&#39;;

class="hl-cmt">// Basic matching
console.log(matchGlob(&#39;my_file.txt&#39;, &#39;*.txt&#39;)); class="hl-cmt">// true
console.log(matchGlob(&#39;src/components/button.ts&#39;, &#39;src/**&#39;)); class="hl-cmt">// true

class="hl-cmt">// Filtering arrays
const files = [&#39;index.js&#39;, &#39;src/main.ts&#39;, &#39;src/utils/helper.js&#39;, &#39;test/test.js&#39;];
const jsFiles = filterByGlob(files, [&#39;*.js&#39;]);
console.log(jsFiles); class="hl-cmt">// [&#39;index.js&#39;, &#39;src/utils/helper.js&#39;, &#39;test/test.js&#39;]

class="hl-cmt">// Tool filtering
const allTools = [&#39;bash&#39;, &#39;git&#39;, &#39;npm&#39;, &#39;web_search&#39;, &#39;view_file&#39;, &#39;mcp__filesystem__read&#39;];
const toolConfig = {
  enabledTools: [&#39;*&#39;, &#39;mcp__*&#39;], class="hl-cmt">// Enable all, but then disable specific ones
  disabledTools: [&#39;web_*&#39;, &#39;mcp__filesystem__read&#39;],
};

const availableTools = filterTools(allTools, toolConfig);
console.log(availableTools); class="hl-cmt">// [&#39;bash&#39;, &#39;git&#39;, &#39;npm&#39;, &#39;view_file&#39;]

console.log(isToolEnabled(&#39;bash&#39;, toolConfig)); class="hl-cmt">// true
console.log(isToolEnabled(&#39;web_search&#39;, toolConfig)); class="hl-cmt">// false
console.log(isToolEnabled(&#39;mcp__filesystem__read&#39;, toolConfig)); class="hl-cmt">// false

7. Input Validator (src/utils/input-validator.ts)

This module provides a comprehensive set of functions for validating various input types and structures, returning detailed validation results or throwing assertion errors.

Purpose: To ensure data integrity and correctness by providing a consistent and extensible way to validate user input, configuration values, or API payloads.

Key Components:

API & Functionality (Highlights):

Basic Type Validators:

Specialized Format Validators:

Composite Validators:

Schema Validation:

Assertion Helpers:

Usage Example:

import {
  validateString,
  validatePositiveInteger,
  validateEmail,
  validateSchema,
  assertValid,
  ValidationError,
} from &#39;./src/utils/input-validator&#39;;

class="hl-cmt">// Basic validation
const nameResult = validateString(&#39;Alice&#39;, { fieldName: &#39;User Name&#39; });
if (nameResult.valid) {
  console.log(`Name: ${nameResult.value}`);
}

const ageResult = validatePositiveInteger(30);
if (!ageResult.valid) {
  console.error(`Age error: ${ageResult.error}`);
}

class="hl-cmt">// Schema validation
const userSchema = {
  username: { validator: validateString, required: true, fieldName: &#39;Username&#39; },
  age: { validator: validatePositiveInteger, required: true, fieldName: &#39;Age&#39; },
  email: { validator: validateEmail, required: false },
  role: { validator: validateString, default: &#39;guest&#39; },
};

const userData = {
  username: &#39;john_doe&#39;,
  age: 25,
  email: &#39;john@example.com&#39;,
};

try {
  const validatedUser = assertValid(validateSchema(userData, userSchema));
  console.log(&#39;Validated User:&#39;, validatedUser);
  class="hl-cmt">// Output: { username: &#39;john_doe&#39;, age: 25, email: &#39;john@example.com&#39;, role: &#39;guest&#39; }

  class="hl-cmt">// Example with missing required field
  const invalidUserData = { username: &#39;jane_doe&#39; };
  assertValid(validateSchema(invalidUserData, userSchema));
} catch (e) {
  if (e instanceof ValidationError) {
    console.error(`Validation Error: ${e.message}`); class="hl-cmt">// Contains &#39;age is required&#39;
  }
}

8. LRU Cache (src/utils/lru-cache.ts)

This module provides a robust Least Recently Used (LRU) cache implementation with optional Time-To-Live (TTL) expiration, detailed statistics, and factory functions for common cache configurations.

Purpose: To efficiently manage a fixed-size cache, automatically evicting the least recently used items when capacity is reached, and supporting time-based expiration for cached data.

Key Components:

API & Functionality:

LRUCache Class:

LRUMap Class:

Factory Functions:

Usage Example:

import { LRUCache, CACHE_SIZES, CACHE_TTL, createMemoryCache } from &#39;./src/utils/lru-cache&#39;;

class="hl-cmt">// Create a cache with a specific size and default TTL
const userCache = new LRUCache<string, { name: string }>({
  maxSize: CACHE_SIZES.MEDIUM, class="hl-cmt">// 500 entries
  ttlMs: CACHE_TTL.HOUR, class="hl-cmt">// 1 hour
  onEvict: (key, value) => console.log(`Evicted user: ${value.name} (${key})`),
});

userCache.set(&#39;user:1&#39;, { name: &#39;Alice&#39; });
userCache.set(&#39;user:2&#39;, { name: &#39;Bob&#39; });

console.log(userCache.get(&#39;user:1&#39;)); class="hl-cmt">// { name: &#39;Alice&#39; }
console.log(userCache.getStats()); class="hl-cmt">// { hits: 1, misses: 0, ... }

class="hl-cmt">// Accessing &#39;user:1&#39; makes it most recently used
userCache.get(&#39;user:1&#39;);

class="hl-cmt">// Fill up and evict
for (let i = 3; i <= CACHE_SIZES.MEDIUM + 1; i++) {
  userCache.set(`user:${i}`, { name: `User ${i}` });
}
class="hl-cmt">// &#39;user:2&#39; should be evicted as it was LRU before &#39;user:1&#39; was accessed

console.log(userCache.has(&#39;user:2&#39;)); class="hl-cmt">// false

class="hl-cmt">// Using a factory function
const analysisCache = createMemoryCache<string>();
analysisCache.set(&#39;report:summary&#39;, &#39;...&#39;);

9. Model Utilities (src/utils/model-utils.ts)

This module provides a centralized way to manage and query information about the various AI models supported by the application, including their providers, capabilities, and default selections.

Purpose: To abstract away the details of different AI models and providers, offering a consistent interface for model selection, validation, and information retrieval.

Key Components:

API & Functionality:

Usage Example:

import {
  isSupportedModel,
  getModelInfo,
  validateModel,
  getDefaultModel,
  getSupportedModels,
  getModelsByProvider,
  suggestModel,
  formatModelInfo,
} from &#39;./src/utils/model-utils&#39;;
import { ValidationError } from &#39;./src/utils/errors&#39;;

class="hl-cmt">// Check model support
console.log(isSupportedModel(&#39;grok-4-latest&#39;)); class="hl-cmt">// true
console.log(isSupportedModel(&#39;unknown-model&#39;)); class="hl-cmt">// false

class="hl-cmt">// Get model information
const grokInfo = getModelInfo(&#39;grok-4-latest&#39;);
console.log(`Grok Max Tokens: ${grokInfo.maxTokens}, Provider: ${grokInfo.provider}`);

class="hl-cmt">// Validate model
try {
  validateModel(&#39;claude-opus-4-6&#39;, true); class="hl-cmt">// OK in strict mode
  validateModel(&#39;non-existent-model&#39;, true); class="hl-cmt">// Throws ValidationError
} catch (e) {
  if (e instanceof ValidationError) {
    console.error(`Model validation failed: ${e.message}`);
  }
}

class="hl-cmt">// Get defaults and lists
console.log(`Default OpenAI model: ${getDefaultModel(&#39;openai&#39;)}`);
console.log(`All supported models: ${getSupportedModels().join(&#39;, &#39;)}`);
console.log(`Google models: ${getModelsByProvider(&#39;google&#39;).join(&#39;, &#39;)}`);

class="hl-cmt">// Suggest models
console.log(`Suggestions for &#39;grok&#39;: ${suggestModel(&#39;grok&#39;).join(&#39;, &#39;)}`);

class="hl-cmt">// Format info
console.log(formatModelInfo(&#39;gpt-4o&#39;));

10. Path Validator (src/utils/path-validator.ts)

The PathValidator module provides robust security checks for file paths, ensuring that operations are confined to allowed directories and preventing path traversal vulnerabilities.

Purpose: To safeguard against malicious path inputs by validating that all file system operations occur within a defined base directory or explicitly allowed paths, and to resolve paths safely.

Key Components:

API & Functionality:

PathValidator Class:

Global Helper Functions:

Usage Example:

import * as path from &#39;path&#39;;
import * as os from &#39;os&#39;;
import {
  initializePathValidator,
  getPathValidator,
  validatePath,
  isPathSafe,
} from &#39;./src/utils/path-validator&#39;;

class="hl-cmt">// Initialize the global validator with the current working directory as base
initializePathValidator({ baseDirectory: process.cwd() });
const validator = getPathValidator();

const safePath = path.join(process.cwd(), &#39;my_project&#39;, &#39;file.txt&#39;);
const unsafePath = &#39;/etc/passwd&#39;;
const traversalPath = path.join(process.cwd(), &#39;..&#39;, &#39;sibling_dir&#39;, &#39;secret.txt&#39;);

class="hl-cmt">// Using the instance
console.log(`Is "${safePath}" safe? ${validator.isSafe(safePath)}`); class="hl-cmt">// true
console.log(`Is "${unsafePath}" safe? ${validator.isSafe(unsafePath)}`); class="hl-cmt">// false

const result = validator.validate(traversalPath);
if (!result.valid) {
  console.error(`Validation error for "${traversalPath}": ${result.error}`);
}

class="hl-cmt">// Using global helpers
const globalSafeResult = validatePath(safePath);
if (globalSafeResult.valid) {
  console.log(`Global check: "${globalSafeResult.resolved}" is valid.`);
}

class="hl-cmt">// Example with additional allowed paths
initializePathValidator({
  baseDirectory: process.cwd(),
  additionalAllowedPaths: [os.tmpdir()],
});
const tmpFile = path.join(os.tmpdir(), &#39;temp_log.txt&#39;);
console.log(`Is "${tmpFile}" safe with additional allowed path? ${isPathSafe(tmpFile)}`); class="hl-cmt">// true

11. Semantic Truncation (src/utils/head-tail-truncation.ts)

This module provides intelligent text truncation capabilities, designed to shorten long outputs while preserving critical information such as error messages, JSON structure, or custom patterns.

Purpose: To make verbose text outputs more manageable for display or processing, without losing essential context that might be buried in the middle of the text.

Key Components:

API & Functionality:

It inserts a message indicating the number of omitted lines and any preserved important lines.

Usage Example:

import {
  semanticTruncate,
  needsTruncation,
} from &#39;./src/utils/head-tail-truncation&#39;;

const longLog = `Line 1: Start of log
Line 2: Some normal output
... (many lines) ...
Line 100: Error: Failed to connect to database
Line 101:   at connectDB (/app/src/db.ts:20:15)
Line 102:   at main (/app/src/index.ts:5:3)
... (many more lines) ...
Line 200: End of log`;

const jsonOutput = `{
  "data": [
    {"id": 1, "value": "A"},
    {"id": 2, "value": "B"},
    class="hl-cmt">// ... 100s of entries ...
    {"id": 999, "value": "Y"},
    {"id": 1000, "value": "Z"}
  ],
  "metadata": {
    "count": 1000,
    "status": "complete"
  }
}`;

class="hl-cmt">// Check if truncation is needed
console.log(`Needs truncation? ${needsTruncation(longLog, 50)}`); class="hl-cmt">// true

class="hl-cmt">// Semantic truncation preserving errors
const truncatedLog = semanticTruncate(longLog, {
  headLines: 5,
  tailLines: 5,
  preserveErrors: true,
});
console.log(&#39;--- Truncated Log (Errors Preserved) ---&#39;);
console.log(truncatedLog.output);
console.log(`Omitted lines: ${truncatedLog.omittedLines}`);

class="hl-cmt">// Semantic truncation preserving JSON structure
const truncatedJson = semanticTruncate(jsonOutput, {
  headLines: 5,
  tailLines: 5,
  preserveJson: true,
});
console.log(&#39;\n--- Truncated JSON (Structure Preserved) ---&#39;);
console.log(truncatedJson.output);

class="hl-cmt">// Custom patterns
const customLog = `Header line 1
Important: User ID 123 processed.
Some other line.
Another line.
Important: Transaction ABC completed.
Footer line 1`;

const truncatedCustom = semanticTruncate(customLog, {
  headLines: 1,
  tailLines: 1,
  preservePatterns: [/Important:/],
});
console.log(&#39;\n--- Truncated Custom (Patterns Preserved) ---&#39;);
console.log(truncatedCustom.output);

12. Settings Manager (src/utils/settings-manager.ts)

The SettingsManager module provides a centralized and hierarchical system for managing application settings, including user-specific and project-specific configurations. It handles persistence to JSON files and provides access to various configuration values.

Purpose: To offer a consistent and robust way to store, retrieve, and update application settings, prioritizing project-level configurations over user-level defaults.

Key Components:

API & Functionality:

Settings Hierarchy: The SettingsManager follows a clear hierarchy for resolving settings:

  1. Project Settings: Settings defined in the project's .codebuddy/config.json take highest precedence.
  2. User Settings: Settings defined in the user's global ~/.codebuddy/settings.json come next.
  3. Application Defaults: Hardcoded default values are used if no other setting is found.

Usage Example:

import { getSettingsManager } from &#39;./src/utils/settings-manager&#39;;

const settingsManager = getSettingsManager();

class="hl-cmt">// Get the current active model
const currentModel = settingsManager.getCurrentModel();
console.log(`Current AI Model: ${currentModel}`);

class="hl-cmt">// Update a user setting
settingsManager.updateUserSetting(&#39;defaultModel&#39;, &#39;grok-3-latest&#39;);
console.log(`Updated default model to: ${settingsManager.getUserSetting(&#39;defaultModel&#39;)}`);

class="hl-cmt">// Get the API key (might be undefined if not set)
const apiKey = settingsManager.getApiKey();
if (apiKey) {
  console.log(&#39;API Key is set.&#39;);
} else {
  console.log(&#39;API Key is not set.&#39;);
}

class="hl-cmt">// Load and inspect project settings
const projectSettings = settingsManager.loadProjectSettings();
console.log(&#39;Project Settings:&#39;, projectSettings);

class="hl-cmt">// Example of how settings are resolved (conceptual, as mocks prevent direct testing here)
class="hl-cmt">// If projectSettings.model is &#39;gpt-4&#39;, it will override userSettings.defaultModel
class="hl-cmt">// If projectSettings.model is undefined, userSettings.defaultModel will be used
class="hl-cmt">// If both are undefined, a hardcoded default will be used.

13. Text Utilities (src/utils/text-utils.ts)

This module provides a collection of basic text manipulation functions, primarily focused on cursor-based editing operations within a string.

Purpose: To offer fundamental building blocks for implementing text editor-like functionalities, such as deleting characters/words and moving the cursor.

Key Components:

API & Functionality:

All functions return an object { text: string, position: number }.

Usage Example:

import {
  deleteCharBefore,
  deleteWordAfter,
  insertText,
  moveToLineStart,
  moveToNextWord,
} from &#39;./src/utils/text-utils&#39;;

let currentText = &#39;hello world&#39;;
let cursor = currentText.length; class="hl-cmt">// At the end

class="hl-cmt">// Delete character before
let result = deleteCharBefore(currentText, cursor);
currentText = result.text; class="hl-cmt">// &#39;hello worl&#39;
cursor = result.position; class="hl-cmt">// 10

class="hl-cmt">// Insert text
result = insertText(currentText, cursor, &#39;d!&#39;);
currentText = result.text; class="hl-cmt">// &#39;hello world!&#39;
cursor = result.position; class="hl-cmt">// 12

class="hl-cmt">// Move to start of next word and delete it
currentText = &#39;first second third&#39;;
cursor = 0;
result = moveToNextWord(currentText, cursor); class="hl-cmt">// cursor moves to &#39; second third&#39;
cursor = result.position; class="hl-cmt">// 6
result = deleteWordAfter(currentText, cursor); class="hl-cmt">// deletes &#39;second &#39;
currentText = result.text; class="hl-cmt">// &#39;first third&#39;
cursor = result.position; class="hl-cmt">// 6 (still at start of &#39;third&#39;)

class="hl-cmt">// Move to line start
currentText = &#39;Line 1\n  Line 2 part 1\nLine 3&#39;;
cursor = 18; class="hl-cmt">// In "part 1" of Line 2
cursor = moveToLineStart(currentText, cursor); class="hl-cmt">// Moves to start of "  Line 2 part 1"
console.log(`Cursor at: ${cursor}`); class="hl-cmt">// 7 (index of &#39; &#39;)

14. Update Notifier (src/utils/update-notifier.ts)

The UpdateNotifier module provides functionality to check for new versions of the application and notify the user when an update is available.

Purpose: To keep users informed about new releases, encouraging them to update to the latest version for new features, bug fixes, and security improvements.

Key Components:

API & Functionality:

Usage Example:

import { UpdateNotifier, compareVersions } from &#39;./src/utils/update-notifier&#39;;

class="hl-cmt">// Version comparison
console.log(`1.0.0 vs 1.0.1: ${compareVersions(&#39;1.0.0&#39;, &#39;1.0.1&#39;)}`); class="hl-cmt">// -1
console.log(`v2.0.0 vs 2.0.0: ${compareVersions(&#39;v2.0.0&#39;, &#39;2.0.0&#39;)}`); class="hl-cmt">// 0

class="hl-cmt">// Initialize notifier
const notifier = new UpdateNotifier({
  enabled: true,
  checkIntervalHours: 1, class="hl-cmt">// Check every hour
});

async function checkForUpdatesAndNotify() {
  console.log(&#39;Checking for updates...&#39;);
  const updateInfo = await notifier.check();

  if (updateInfo && updateInfo.updateAvailable) {
    const notificationMessage = notifier.formatNotification();
    if (notificationMessage) {
      console.log(&#39;\n--- UPDATE AVAILABLE ---&#39;);
      console.log(notificationMessage);
      console.log(&#39;------------------------\n&#39;);
    }
  } else {
    console.log(&#39;No updates available or check skipped.&#39;);
  }
}

class="hl-cmt">// In a real application, this would run periodically or on startup
class="hl-cmt">// checkForUpdatesAndNotify();