OneApp Docs
PackagesCore

@repo/core-utils

Framework-agnostic utilities for string processing, caching, logging, code analysis, and performance monitoring. 50+ battle-tested implementations. Works in browser, edge, and Node.js. Consumed from source for optimal tree-shaking.

Quick Start

Add battle-tested utilities in 5 minutes:

pnpm add @repo/core-utils

Dual exports: /shared (all environments), /server (Node.js only). Skip to Quick Start →

Why @repo/core-utils?

Every package reimplements caching differently. Circular JSON handling varies (some crash, some truncate). Loggers lack async buffering and file rotation. Memory pressure causes OOM errors. Code analysis tools are scattered. String processing has edge cases (circular refs, large objects, special types).

@repo/core-utils solves this with framework-agnostic utilities and dual export paths for environment-specific code.

Production-ready with 50+ utilities, comprehensive tests, minimal dependencies, and dual /shared (environment-neutral) and /server (Node.js) exports.

Use cases

  • Circular-safe JSON — Stringify objects with circular references safely
  • LRU caching with TTL — Cache with automatic eviction and expiration
  • Async logging — High-performance logging with buffering and rotation
  • Code analysis — Discover files, analyze dependencies, scan for security issues
  • Memory monitoring — Track heap usage, auto-cleanup on pressure

How it works

@repo/core-utils provides dual export paths for environment compatibility:

// Shared utilities (browser, edge, Node.js)
import { safeStringify } from "@repo/core-utils/shared/stringify";

const obj = { a: 1 };
obj.self = obj; // Circular reference

const json = safeStringify(obj, 75000);
// => {"a":1,"self":"[Circular Reference]"}

// Server utilities (Node.js only)
import { BoundedCache } from "@repo/core-utils/server/cache";

const cache = new BoundedCache({
  maxSize: 100,
  ttl: 1800000, // 30 minutes
  enableAnalytics: true
});

cache.set("key", value);
const analytics = cache.getAnalytics();
console.log(analytics.hitRate); // Cache hit rate %

Uses /shared exports for environment-neutral code (pure JavaScript), and /server exports for Node.js features (file system, Buffer, process memory).

Key features

Dual export paths/shared (all environments), /server (Node.js only)

Circular-safe JSON — Handle circular references, deep nesting, large objects

Advanced caching — LRU + TTL, memory-aware, centralized registry

Async logging — Buffered writes, file rotation, performance stats

Code analysis — File discovery, pattern matching, dependency graphs, security scanning

Tree-shakeable — Consumed from source for optimal bundle size

Quick Start

1. Install the package

pnpm add @repo/core-utils

2. Use shared utilities for JSON (all environments)

app/components/DebugPanel.tsx
"use client";

import { safeStringify } from "@repo/core-utils/shared/stringify";

export function DebugPanel({ data }: { data: unknown }) {
  // Works in browser - handles circular refs safely
  const json = safeStringify(data, 50000);

  return <pre className="text-xs">{json}</pre>;
}
middleware.ts
import { NextResponse } from "next/server";
import { safeStringify } from "@repo/core-utils/shared/stringify";

export function middleware(request: Request) {
  // Works in edge runtime
  console.log(safeStringify(request.headers));
  return NextResponse.next();
}

3. Use server utilities for caching (Node.js only)

lib/cache.ts
import { BoundedCache } from "@repo/core-utils/server/cache";

export const userCache = new BoundedCache({
  maxSize: 100,
  ttl: 1800000, // 30 minutes
  enableAnalytics: true
});

export async function getCachedUser(id: string) {
  const cached = userCache.get(id);
  if (cached) return cached;

  const user = await fetchUser(id);
  userCache.set(id, user);
  return user;
}
app/api/cache-stats/route.ts
import { userCache } from "#/lib/cache";

export async function GET() {
  const analytics = userCache.getAnalytics();

  return Response.json({
    hitRate: analytics.hitRate,
    size: analytics.size,
    memoryUsage: analytics.memoryUsage
  });
}

4. Add logging with AsyncLogger (Node.js only)

lib/logger.ts
import { AsyncLogger } from "@repo/core-utils/server/logger";

export const logger = new AsyncLogger({
  sessionId: "app-session",
  logDir: "./logs",
  logLevel: "info",
  maxBufferSize: 16384, // 16KB buffer
  maxFileSize: 10485760 // 10MB rotation
});

await logger.init();
app/api/process/route.ts
import { logger } from "#/lib/logger";

export async function POST(request: Request) {
  logger.log("Processing started", "info");

  try {
    // Process data
    logger.log("Processing completed", "info");
  } catch (error) {
    logger.log("Processing failed", "error", { error });
  }

  return Response.json({ success: true });
}

That's it! You now have environment-neutral JSON processing, server-side caching with analytics, and high-performance async logging.

Memory-aware caching

Automatically clean cache on memory pressure:

import { MemoryAwareCache } from "@repo/core-utils/server/memory-aware-cache";

const cache = new MemoryAwareCache({
  maxSize: 1000,
  ttl: 3600000,
  memoryThreshold: 150 * 1024 * 1024 // Auto-cleanup at 150MB
});

Technical Details

For Developers: Technical implementation details

Overview

PropertyValue
Locationpackages/core-utils
DependenciesMinimal (glob, lru-cache, p-queue, zod)
Utilities50+ utilities across 6 categories
BuildNo (consumed from source)

Architecture: Two Export Paths

/shared - Environment-Neutral

Pure JavaScript utilities that work everywhere:

  • ✅ Browser (client components)
  • ✅ Edge runtime (middleware)
  • ✅ Node.js (server components)
  • ✅ Packages (maximum portability)

Key Feature: Zero Node.js dependencies

/server - Node.js-Specific

Advanced utilities with Node.js features:

  • ✅ File system operations
  • ✅ Buffer handling
  • ✅ Process memory monitoring
  • ✅ Performance profiling

Key Feature: Enhanced with memory tracking and advanced features

Export Paths

PathDescription
@repo/core-utils/shared/*Environment-neutral utilities
@repo/core-utils/server/*Node.js-specific utilities

String Processing

safeStringify (Shared)

Pure JSON stringification with circular reference handling.

import { safeStringify } from "@repo/core-utils/shared/stringify";

const obj = { a: 1 };
obj.self = obj; // Circular reference

// highlight-next-line
const json = safeStringify(obj, 75000);
// Output: {"a":1,"self":"[Circular Reference]"}

Handles:

  • Circular references
  • undefined, functions, symbols
  • Map, Set, Error objects
  • Deep nesting (max depth: 20)
  • Large objects (configurable truncation)

safeStringifyPure (Shared)

With metadata about the stringification process:

import { safeStringifyPure } from "@repo/core-utils/shared/stringify";

// highlight-start
const result = safeStringifyPure(obj, {
  prettify: true,
  maxLength: 50000
});
// highlight-end

console.log(result.result); // JSON string
console.log(result.metadata.circularRefs); // Number of circular refs
console.log(result.metadata.truncated); // Boolean
console.log(result.metadata.originalLength); // Original length

SafeStringifier (Server)

Advanced stringifier with Node.js features:

import { SafeStringifier } from "@repo/core-utils/server/stringify-advanced";

// highlight-start
const stringifier = new SafeStringifier({
  maxLength: 100000,
  prettify: true,
  includeMetadata: true
});
// highlight-end

const result = stringifier.stringify(obj);

console.log(result.metadata.memoryUsage); // Heap memory used
console.log(result.metadata.executionTime); // Time in ms
console.log(result.metadata.circularRefs); // Circular references found

Caching

BoundedCache (Server)

LRU + TTL

Combines LRU eviction with TTL expiration for optimal memory management.

LRU cache with TTL, analytics, and automatic memory management:

import { BoundedCache } from "@repo/core-utils/server/cache";

// highlight-start
const cache = new BoundedCache({
  maxSize: 100,
  ttl: 1800000, // 30 minutes
  enableAnalytics: true
});
// highlight-end

cache.set("key", value);
const value = cache.get("key");

// Analytics
const analytics = cache.getAnalytics();
console.log(analytics.hitRate); // Cache hit rate %
console.log(analytics.memoryUsage); // Estimated memory usage
console.log(analytics.size); // Current size

// Cleanup
const cleaned = cache.cleanup(); // Smart cleanup
const forceCleaned = cache.cleanup(true); // Force cleanup

CacheRegistry (Server)

Centralized cache management across the application:

import { globalCacheRegistry } from "@repo/core-utils/server/cache";

// Create named caches
// highlight-start
const userCache = globalCacheRegistry.create("user-cache", {
  maxSize: 50,
  ttl: 600000
});
// highlight-end

const productCache = globalCacheRegistry.create("product-cache", {
  maxSize: 100,
  ttl: 1800000
});

// Retrieve existing cache
const sameCache = globalCacheRegistry.get("user-cache");

// Global analytics
const analytics = globalCacheRegistry.getGlobalAnalytics();
console.log(analytics.totalHits);
console.log(analytics.totalMisses);
console.log(analytics.cacheCount);

// Cleanup all caches
const results = globalCacheRegistry.cleanupAll();

MemoryAwareCache (Server)

Memory Pressure

Automatically evicts entries when heap memory exceeds 150MB to prevent OOM errors.

Advanced cache with automatic memory pressure detection:

import { MemoryAwareCache } from "@repo/core-utils/server/memory-aware-cache";

// highlight-start
const cache = new MemoryAwareCache({
  maxSize: 1000,
  ttl: 3600000,
  memoryThreshold: 150 * 1024 * 1024 // 150MB
});
// highlight-end

// Automatically monitors memory and cleans when needed
cache.set("key", largeObject);

const stats = cache.getStats();
console.log(stats.memoryPressureCleanups); // Auto-cleanup count

Logging

AsyncLogger (Server)

High Performance

Buffers log messages in memory and flushes asynchronously for minimal performance impact.

High-performance async logger with buffering and file rotation:

import { AsyncLogger } from "@repo/core-utils/server/logger";

// highlight-start
const logger = new AsyncLogger({
  sessionId: "analysis-session-123",
  logDir: "./logs",
  logLevel: "info",
  maxBufferSize: 16384, // 16KB buffer
  maxFileSize: 10485760, // 10MB before rotation
  maxFiles: 5 // Keep 5 rotated files
});
// highlight-end

await logger.init();

logger.log("Processing started", "info");
logger.log("Error occurred", "error", { details: "..." });

// Force flush buffer to disk
logger.flush();

// Get statistics
const stats = logger.getStats();
console.log(stats.messagesLogged);
console.log(stats.bytesWritten);
console.log(stats.flushCount);

// Cleanup
await logger.close();

LoggerRegistry (Server)

Centralized logger management:

import { globalLoggerRegistry } from "@repo/core-utils/server/logger";

// Create named logger
// highlight-start
const logger = globalLoggerRegistry.create("main-logger", {
  sessionId: "session-123",
  logLevel: "debug"
});
// highlight-end

await logger.init();

// Retrieve logger anywhere
const sameLogger = globalLoggerRegistry.get("main-logger");

// Global stats
const stats = globalLoggerRegistry.getGlobalStats();
console.log(stats.totalLoggers);
console.log(stats.totalMessages);

// Close specific logger
await globalLoggerRegistry.close("main-logger");

// Close all loggers
await globalLoggerRegistry.closeAll();

Code Analysis (Server)

File Discovery

import { FileDiscovery } from "@repo/core-utils/server/file-discovery";

// highlight-start
const discovery = new FileDiscovery({
  rootDir: "./src",
  ignorePatterns: ["**/*.test.ts", "**/node_modules/**"]
});
// highlight-end

const files = await discovery.findFiles("**/*.ts");
console.log(files); // Array of file paths

Pattern Analyzer

import { PatternAnalyzer } from "@repo/core-utils/server/pattern-analyzer";

// highlight-start
const analyzer = new PatternAnalyzer({
  patterns: [
    { name: "console-log", pattern: /console\.log/g },
    { name: "todo-comment", pattern: /\/\/\s*TODO:/gi }
  ]
});
// highlight-end

const results = await analyzer.analyze("./src");
console.log(results.patterns); // Found patterns by file

Dependency Analyzer

import { DependencyAnalyzer } from "@repo/core-utils/server/dependency-analyzer";

const analyzer = new DependencyAnalyzer();

// highlight-start
const graph = await analyzer.analyzeDependencies("./src");
// highlight-end

console.log(graph.nodes); // Files
console.log(graph.edges); // Dependencies
console.log(graph.circularDependencies); // Circular deps found

Security Scanner

import { SecurityScanner } from "@repo/core-utils/server/security-scanner";

// highlight-start
const scanner = new SecurityScanner({
  rules: ["no-eval", "no-hardcoded-secrets", "no-sql-injection", "no-xss"]
});
// highlight-end

const results = await scanner.scan("./src");
console.log(results.vulnerabilities); // Found security issues

Code Transformation

import { CodeTransformer } from "@repo/core-utils/server/code-transformation";

const transformer = new CodeTransformer();

// highlight-start
const result = await transformer.transform("./src/file.ts", {
  replaceImports: {
    from: "@old/package",
    to: "@new/package"
  }
});
// highlight-end

console.log(result.modified); // Boolean
console.log(result.ast); // AST if needed

Performance & Monitoring (Server)

Performance Tracker

import { PerformanceTracker } from "@repo/core-utils/server/performance";

const tracker = new PerformanceTracker();

// highlight-start
tracker.start("operation-name");
// ... do work ...
tracker.end("operation-name");
// highlight-end

const metrics = tracker.getMetrics("operation-name");
console.log(metrics.duration); // Duration in ms
console.log(metrics.count); // Number of times called
console.log(metrics.average); // Average duration

Memory Monitor

import { MemoryMonitor } from "@repo/core-utils/server/advanced-memory-monitor";

// highlight-start
const monitor = new MemoryMonitor({
  interval: 5000, // Check every 5 seconds
  threshold: 200 * 1024 * 1024, // 200MB
  onThresholdExceeded: (usage) => {
    console.warn(`Memory usage: ${usage.heapUsed / 1024 / 1024}MB`);
  }
});
// highlight-end

monitor.start();

// Get current usage
const usage = monitor.getUsage();
console.log(usage.heapUsed);
console.log(usage.heapTotal);
console.log(usage.external);

// Stop monitoring
monitor.stop();

Utility Helpers (Server)

Retry Logic

import { retry } from "@repo/core-utils/server/retry";

// highlight-start
const result = await retry(
  async () => {
    return await fetch("https://api.example.com/data");
  },
  {
    maxAttempts: 3,
    delay: 1000,
    exponentialBackoff: true
  }
);
// highlight-end

Batch Processor

import { BatchProcessor } from "@repo/core-utils/server/batch-processor";

// highlight-start
const processor = new BatchProcessor({
  batchSize: 100,
  concurrency: 5,
  processFunc: async (batch) => {
    // Process batch of items
    return batch.map((item) => processItem(item));
  }
});
// highlight-end

const results = await processor.process(items);

Worker Pool

import { WorkerPool } from "@repo/core-utils/server/worker-pool";

// highlight-start
const pool = new WorkerPool({
  maxWorkers: 4,
  workerScript: "./worker.js"
});
// highlight-end

await pool.init();

const result = await pool.execute({ task: "process-data", data: "..." });

await pool.shutdown();

Abort Support

import { withAbort } from "@repo/core-utils/server/abort-support";

const controller = new AbortController();

// highlight-start
const result = await withAbort(async (signal) => {
  return await longRunningOperation(signal);
}, controller.signal);
// highlight-end

// Abort if needed
controller.abort();

Usage by Environment

Next.js Server Components

// ✅ Can use server utilities
import { SafeStringifier } from "@repo/core-utils/server/stringify-advanced";

export default async function Page() {
  const data = await fetchData();
  const stringifier = new SafeStringifier();
  const json = stringifier.stringify(data);

  return <pre>{json.result}</pre>;
}

Next.js Client Components

"use client";

// ✅ Must use shared utilities only
import { safeStringify } from "@repo/core-utils/shared/stringify";

export function ClientComponent({ data }: Props) {
  const json = safeStringify(data, 50000);
  return <pre>{json}</pre>;
}

Edge Middleware

// ✅ Must use shared utilities only
import { safeStringify } from "@repo/core-utils/shared/stringify";

export function middleware(req: NextRequest) {
  const debug = safeStringify(req.headers);
  console.log(debug);
  return NextResponse.next();
}

Packages

// ✅ Prefer shared utilities for maximum portability
import { safeStringify } from "@repo/core-utils/shared/stringify";

// ⚠️ Use server utilities only when Node.js features required
import { AsyncLogger } from "@repo/core-utils/server/logger";

Testing

# Run tests
pnpm --filter @repo/core-utils test

# Watch mode
pnpm --filter @repo/core-utils test --watch

# Coverage
pnpm --filter @repo/core-utils test:coverage

Migration from @repo/mcp-server

Backward Compatibility

The @repo/mcp-server package re-exports these utilities for backward compatibility.

Before:

import { safeStringify } from "@repo/mcp-server/utils/stringify";
import { BoundedCache } from "@repo/mcp-server/utils/cache";

After:

import { safeStringify } from "@repo/core-utils/shared/stringify";
import { BoundedCache } from "@repo/core-utils/server/cache";

Design Principles

  1. Framework-agnostic - Works with Next.js, React, Node.js, edge runtime
  2. Zero dependencies - Minimal external dependencies (only catalog versions)
  3. Type-safe - Full TypeScript support with exported types
  4. Well-tested - Comprehensive test coverage
  5. Performance - Optimized for production use
  6. Reusable - DRY principle - single implementation for all packages

External Resources

On this page