CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-moize

Blazing fast memoization library for JavaScript with comprehensive configuration options and React support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

cache-introspection.mddocs/

Cache Introspection

Methods available on memoized functions for direct cache access, manipulation, and introspection, enabling fine-grained control over cached data.

Capabilities

Cache State Access

Direct access to the current cache state and snapshots.

interface Moized {
  /**
   * Current cache state containing all cached entries
   */
  cache: Cache<MoizeableFn>;
  
  /**
   * Snapshot of cache state at the time of memoization creation
   */
  cacheSnapshot: Cache<MoizeableFn>;
  
  /**
   * Array of active expirations for TTL-based caching
   */
  expirations: Expiration[];
  
  /**
   * Snapshot of expirations at the time of memoization creation
   */
  expirationsSnapshot: Expiration[];
}

type Cache<MoizeableFn extends Moizeable = Moizeable> = BaseCache<MoizeableFn>;

type Expiration = {
  expirationMethod: () => void;
  key: Key;
  timeoutId: ReturnType<typeof setTimeout>;
};

Usage Examples:

import moize from "moize";

const fibonacci = (n: number): number => {
  if (n < 2) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
};

const memoizedFib = moize.maxSize(10)(fibonacci);

// Generate some cached entries
memoizedFib(5);
memoizedFib(8);
memoizedFib(10);

// Inspect cache state
console.log('Cache entries:', memoizedFib.cache.size);
console.log('Cache keys:', memoizedFib.keys());
console.log('Cache values:', memoizedFib.values());

// For TTL-enabled functions
const apiCall = moize.maxAge(30000)(async (endpoint: string) => {
  const response = await fetch(endpoint);
  return response.json();
});

// Check active expirations
console.log('Active expirations:', apiCall.expirations.length);

Cache Entry Retrieval

Get specific cached values using cache keys.

interface Moized {
  /**
   * Retrieve a cached value for the given key
   * @param key The cache key (argument array) to look up
   * @returns The cached value, or undefined if not found
   */
  get(key: Key): any;
  
  /**
   * Check if a cache entry exists for the given key
   * @param key The cache key (argument array) to check
   * @returns Whether the key exists in cache
   */
  has(key: Key): boolean;
}

type Key<Arg extends any = any> = Arg[];

Usage Examples:

import moize from "moize";

const add = (a: number, b: number) => a + b;
const memoizedAdd = moize(add);

// Call function to cache result
memoizedAdd(2, 3); // 5

// Retrieve cached value directly
const cachedResult = memoizedAdd.get([2, 3]);
console.log(cachedResult); // 5

// Check if key exists
console.log(memoizedAdd.has([2, 3])); // true
console.log(memoizedAdd.has([1, 1])); // false

// Complex key example
const processUser = (user: { id: string; name: string }) => {
  return `User: ${user.name} (${user.id})`;
};

const memoizedProcess = moize.deep(processUser);

const userObj = { id: "123", name: "Alice" };
memoizedProcess(userObj);

// For deep equality, must use equivalent object
console.log(memoizedProcess.has([userObj])); // true
console.log(memoizedProcess.has([{ id: "123", name: "Alice" }])); // true (deep equality)

Cache Manipulation

Directly manipulate cache entries by adding, updating, or removing cached values.

interface Moized {
  /**
   * Manually set a cache entry
   * @param key The cache key (argument array)
   * @param value The value to cache
   */
  set(key: Key, value: any): void;
  
  /**
   * Remove a specific cache entry
   * @param key The cache key (argument array) to remove
   */
  remove(key: Key): void;
  
  /**
   * Clear all cached entries
   */
  clear(): void;
}

Usage Examples:

import moize from "moize";

const expensiveCalculation = (n: number) => {
  console.log(`Computing for ${n}`);
  return n * n * n;
};

const memoized = moize.maxSize(5)(expensiveCalculation);

// Pre-populate cache with known values
memoized.set([1], 1);
memoized.set([2], 8);
memoized.set([3], 27);

console.log(memoized(1)); // 1 (from cache, no computation)
console.log(memoized(2)); // 8 (from cache, no computation)
console.log(memoized(4)); // 64 (computed, since not pre-cached)

// Remove specific entry
memoized.remove([2]);
console.log(memoized.has([2])); // false

// Clear all cache
memoized.clear();
console.log(memoized.keys().length); // 0

// Update existing cache entry
memoized(5); // 125 (computed)
memoized.set([5], 999); // Override with custom value
console.log(memoized(5)); // 999 (custom value)

Cache Inspection

Inspect all cache keys and values for debugging and analysis.

interface Moized {
  /**
   * Get all cache keys
   * @returns Array-like object containing all cache keys
   */
  keys(): Cache<MoizeableFn>['keys'];
  
  /**
   * Get all cached values
   * @returns Array-like object containing all cached values
   */
  values(): Cache<MoizeableFn>['values'];
}

Usage Examples:

import moize from "moize";

const processData = (type: string, data: any[]) => {
  return { type, count: data.length, processed: true };
};

const memoized = moize.maxSize(10)(processData);

// Generate some cache entries
memoized("users", [1, 2, 3]);
memoized("posts", [{ id: 1 }, { id: 2 }]);
memoized("comments", []);

// Inspect all keys
const keys = Array.from(memoized.keys());
console.log('Cache keys:', keys);
// [["users", [1, 2, 3]], ["posts", [{ id: 1 }, { id: 2 }]], ["comments", []]]

// Inspect all values
const values = Array.from(memoized.values());
console.log('Cache values:', values);
// [
//   { type: "users", count: 3, processed: true },
//   { type: "posts", count: 2, processed: true },
//   { type: "comments", count: 0, processed: true }
// ]

// Debug cache contents
function debugCache(memoizedFn: any, name: string) {
  console.log(`\n=== ${name} Cache Debug ===`);
  console.log(`Cache size: ${Array.from(memoizedFn.keys()).length}`);
  
  const keys = Array.from(memoizedFn.keys());
  const values = Array.from(memoizedFn.values());
  
  keys.forEach((key, index) => {
    console.log(`Key ${index}:`, JSON.stringify(key));
    console.log(`Value ${index}:`, values[index]);
  });
}

debugCache(memoized, 'processData');

Function Introspection

Get information about the memoized function configuration and original function.

interface Moized {
  /**
   * The original unmemoized function
   */
  originalFunction: MoizeableFn;
  
  /**
   * The options used to create this memoized function
   */
  options: CombinedOptions;
  
  /**
   * Internal micro-memoize options (for advanced introspection)
   */
  _microMemoizeOptions: MicroMemoizeOptions<MoizeableFn>;
  
  /**
   * Type guard function that always returns true for memoized functions
   * @returns Always true (indicates this is a memoized function)
   */
  isMoized(): true;
}

Usage Examples:

import moize from "moize";

const originalAdd = (a: number, b: number) => a + b;
const memoizedAdd = moize.maxSize(20).maxAge(5000).profile('math')(originalAdd);

// Access original function
console.log(memoizedAdd.originalFunction === originalAdd); // true
console.log(memoizedAdd.originalFunction.name); // "originalAdd"

// Inspect configuration
console.log(memoizedAdd.options);
// {
//   maxSize: 20,
//   maxAge: 5000,
//   profileName: 'math',
//   isDeepEqual: false,
//   isPromise: false,
//   // ... other default options
// }

// Type checking
console.log(memoizedAdd.isMoized()); // true

// Check if a function is memoized
function isMemoizedFunction(fn: any): boolean {
  return typeof fn === 'function' && typeof fn.isMoized === 'function' && fn.isMoized();
}

console.log(isMemoizedFunction(memoizedAdd)); // true
console.log(isMemoizedFunction(originalAdd)); // false

// Create cache debugging utility
function createCacheInspector(memoizedFn: any) {
  return {
    getCacheInfo() {
      return {
        size: Array.from(memoizedFn.keys()).length,
        maxSize: memoizedFn.options.maxSize,
        maxAge: memoizedFn.options.maxAge,
        profileName: memoizedFn.options.profileName,
        hasExpirations: memoizedFn.expirations.length > 0
      };
    },
    
    dumpCache() {
      const keys = Array.from(memoizedFn.keys());
      const values = Array.from(memoizedFn.values());
      
      return keys.map((key, index) => ({
        key,
        value: values[index],
        index
      }));
    },
    
    findByKey(searchKey: any[]) {
      const keys = Array.from(memoizedFn.keys());
      const values = Array.from(memoizedFn.values());
      
      const index = keys.findIndex(key => 
        JSON.stringify(key) === JSON.stringify(searchKey)
      );
      
      return index >= 0 ? { key: keys[index], value: values[index] } : null;
    }
  };
}

const inspector = createCacheInspector(memoizedAdd);
memoizedAdd(1, 2);
memoizedAdd(3, 4);

console.log(inspector.getCacheInfo());
console.log(inspector.dumpCache());
console.log(inspector.findByKey([1, 2]));

docs

argument-transformation.md

cache-introspection.md

cache-management.md

core-memoization.md

equality-comparison.md

index.md

specialized-memoization.md

statistics-profiling.md

utility-methods.md

tile.json