or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ast-extraction.mddirectives.mddocument-transformation.mdfragments.mdindex.mdstore-utilities.mdutility-functions.md
tile.json

utility-functions.mddocs/

Utility Functions

General-purpose utility functions for object manipulation, environment detection, error handling, and data processing.

Capabilities

Deep Cloning

Creates deep copies of objects and arrays, handling circular references and preserving prototypes.

/**
 * Deeply clone a value to create a new instance
 * @param value - Value to clone
 * @returns Deep copy of the input value
 */
function cloneDeep<T>(value: T): T;

Usage Examples:

import { cloneDeep } from "apollo-utilities";

// Clone simple objects
const original = { name: "John", age: 30, hobbies: ["reading", "gaming"] };
const cloned = cloneDeep(original);

cloned.name = "Jane";
cloned.hobbies.push("cooking");

console.log(original.name); // "John" (unchanged)
console.log(original.hobbies); // ["reading", "gaming"] (unchanged)
console.log(cloned.name); // "Jane"
console.log(cloned.hobbies); // ["reading", "gaming", "cooking"]

// Clone nested objects
const complex = {
  user: {
    profile: {
      settings: {
        theme: "dark",
        notifications: true
      }
    }
  },
  posts: [
    { title: "Post 1", tags: ["tech"] },
    { title: "Post 2", tags: ["life"] }
  ]
};

const clonedComplex = cloneDeep(complex);
clonedComplex.user.profile.settings.theme = "light";
console.log(complex.user.profile.settings.theme); // "dark" (unchanged)

// Handles circular references
const circular = { name: "test" };
circular.self = circular;
const clonedCircular = cloneDeep(circular);
console.log(clonedCircular.self === clonedCircular); // true
console.log(clonedCircular === circular); // false

Equality Checking

Deep equality comparison function re-exported from @wry/equality.

/**
 * Deep equality comparison (re-exported from @wry/equality)
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns true if values are deeply equal
 */
function isEqual(a: any, b: any): boolean;

Usage Examples:

import { isEqual } from "apollo-utilities";

// Primitive values
console.log(isEqual(42, 42)); // true
console.log(isEqual("hello", "hello")); // true
console.log(isEqual(true, false)); // false

// Objects
const obj1 = { name: "John", age: 30, hobbies: ["reading"] };
const obj2 = { name: "John", age: 30, hobbies: ["reading"] };
const obj3 = { name: "Jane", age: 30, hobbies: ["reading"] };

console.log(isEqual(obj1, obj2)); // true (same content)
console.log(isEqual(obj1, obj3)); // false (different name)
console.log(obj1 === obj2); // false (different references)

// Arrays
console.log(isEqual([1, 2, 3], [1, 2, 3])); // true
console.log(isEqual([1, 2, 3], [3, 2, 1])); // false (different order)

// Nested structures
const nested1 = { user: { profile: { name: "John" } } };
const nested2 = { user: { profile: { name: "John" } } };
console.log(isEqual(nested1, nested2)); // true

Object Assignment

Object.assign polyfill with multiple overloads for type safety.

/**
 * Merge properties from source objects into target object
 * @param target - Target object to merge into
 * @param sources - Source objects to merge from
 * @returns Target object with merged properties
 */
function assign<A, B>(a: A, b: B): A & B;
function assign<A, B, C>(a: A, b: B, c: C): A & B & C;
function assign<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
function assign<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E): A & B & C & D & E;
function assign(target: any, ...sources: Array<any>): any;

Usage Examples:

import { assign } from "apollo-utilities";

// Basic assignment
const target = { name: "John" };
const source = { age: 30, city: "New York" };
const result = assign(target, source);

console.log(result); // { name: "John", age: 30, city: "New York" }
console.log(target === result); // true (target is modified)

// Multiple sources
const base = { a: 1 };
const ext1 = { b: 2 };
const ext2 = { c: 3 };
const merged = assign(base, ext1, ext2);
console.log(merged); // { a: 1, b: 2, c: 3 }

// Property override
const obj1 = { name: "John", age: 25 };
const obj2 = { age: 30, city: "Boston" };
const final = assign(obj1, obj2);
console.log(final); // { name: "John", age: 30, city: "Boston" }

// Handle null/undefined sources
const safe = assign({ a: 1 }, null, undefined, { b: 2 });
console.log(safe); // { a: 1, b: 2 }

Deep Merging

Advanced object merging with memory-efficient sharing and type inference.

/**
 * Deep merge multiple objects with memory sharing
 * @param sources - Objects to merge
 * @returns Merged object with shared memory where possible
 */
function mergeDeep<T extends any[]>(...sources: T): TupleToIntersection<T>;

/**
 * Deep merge array of objects
 * @param sources - Array of objects to merge
 * @returns Merged object
 */
function mergeDeepArray<T>(sources: T[]): T;

Usage Examples:

import { mergeDeep, mergeDeepArray } from "apollo-utilities";

// Basic deep merge
const base = {
  user: {
    name: "John",
    settings: {
      theme: "dark",
      notifications: true
    }
  }
};

const update = {
  user: {
    age: 30,
    settings: {
      language: "en"
    }
  }
};

const merged = mergeDeep(base, update);
console.log(merged);
// {
//   user: {
//     name: "John",        // preserved from base
//     age: 30,             // added from update
//     settings: {
//       theme: "dark",     // preserved from base
//       notifications: true, // preserved from base
//       language: "en"     // added from update
//     }
//   }
// }

// Multiple objects
const config1 = { api: { timeout: 5000 } };
const config2 = { api: { retries: 3 } };
const config3 = { ui: { theme: "light" } };

const finalConfig = mergeDeep(config1, config2, config3);
console.log(finalConfig);
// {
//   api: { timeout: 5000, retries: 3 },
//   ui: { theme: "light" }
// }

// Array version
const configs = [config1, config2, config3];
const arrayMerged = mergeDeepArray(configs);
console.log(isEqual(finalConfig, arrayMerged)); // true

Environment Detection

Functions for detecting the current runtime environment.

/**
 * Get current environment from NODE_ENV
 * @returns Environment string or "development" as default
 */
function getEnv(): string | undefined;

/**
 * Check if current environment matches specified environment
 * @param env - Environment name to check
 * @returns true if current environment matches
 */
function isEnv(env: string): boolean;

/**
 * Check if running in production environment
 * @returns true if NODE_ENV is "production"
 */
function isProduction(): boolean;

/**
 * Check if running in development environment
 * @returns true if NODE_ENV is "development"
 */
function isDevelopment(): boolean;

/**
 * Check if running in test environment
 * @returns true if NODE_ENV is "test"
 */
function isTest(): boolean;

Usage Examples:

import { 
  getEnv, 
  isProduction, 
  isDevelopment, 
  isTest, 
  isEnv 
} from "apollo-utilities";

// Check current environment
console.log(getEnv()); // "development" (or current NODE_ENV)

// Conditional logic based on environment
if (isProduction()) {
  // Production-only code
  console.log("Running in production mode");
} else if (isDevelopment()) {
  // Development-only code
  console.log("Development mode - extra logging enabled");
}

if (isTest()) {
  // Test-specific behavior
  console.log("Running in test environment");
}

// Custom environment check
if (isEnv("staging")) {
  console.log("Running in staging environment");
}

// Example usage in configuration
const config = {
  apiUrl: isProduction() 
    ? "https://api.production.com" 
    : "https://api.dev.com",
  debug: isDevelopment(),
  logLevel: isTest() ? "silent" : "info"
};

Error Handling

Utilities for safe function execution and GraphQL result validation.

/**
 * Execute function safely and log any errors
 * @param f - Function to execute
 * @returns Function result or undefined if error occurred
 */
function tryFunctionOrLogError(f: Function): any;

/**
 * Check if GraphQL execution result has errors
 * @param result - GraphQL execution result
 * @returns true if result contains errors
 */
function graphQLResultHasError(result: ExecutionResult): boolean;

Usage Examples:

import { tryFunctionOrLogError, graphQLResultHasError } from "apollo-utilities";

// Safe function execution
const riskyFunction = () => {
  throw new Error("Something went wrong");
};

const safeFunction = () => {
  return { success: true };
};

const result1 = tryFunctionOrLogError(riskyFunction);
console.log(result1); // undefined (error logged to console)

const result2 = tryFunctionOrLogError(safeFunction);
console.log(result2); // { success: true }

// GraphQL result validation
const successResult = {
  data: { user: { name: "John" } }
};

const errorResult = {
  data: null,
  errors: [{ message: "User not found" }]
};

console.log(graphQLResultHasError(successResult)); // false
console.log(graphQLResultHasError(errorResult)); // true

// Use in GraphQL client code
async function executeQuery(query) {
  const result = await client.query({ query });
  
  if (graphQLResultHasError(result)) {
    console.error("Query failed:", result.errors);
    return null;
  }
  
  return result.data;
}

Development Warnings

Utility for displaying warnings only once in development environment.

/**
 * Print warning once in development environment
 * @param msg - Warning message to display
 * @param type - Message type: "warn" or "error" (default: "warn")
 */
function warnOnceInDevelopment(msg: string, type?: string): void;

Usage Examples:

import { warnOnceInDevelopment } from "apollo-utilities";

// Basic warning (only shows once in development)
function deprecatedFunction() {
  warnOnceInDevelopment("deprecatedFunction is deprecated, use newFunction instead");
  // Function implementation...
}

// Call multiple times - warning only appears once
deprecatedFunction(); // Warning logged
deprecatedFunction(); // No warning (already shown)
deprecatedFunction(); // No warning (already shown)

// Error-level warning
function riskyOperation() {
  warnOnceInDevelopment(
    "riskyOperation may cause data loss in certain conditions", 
    "error"
  );
}

// Conditional warnings
function configValidation(config) {
  if (!config.apiKey) {
    warnOnceInDevelopment("API key not provided - using default configuration");
  }
  
  if (config.timeout < 1000) {
    warnOnceInDevelopment("Timeout less than 1000ms may cause reliability issues");
  }
}

Data Processing Utilities

Additional utilities for data processing and development aids.

/**
 * Remove symbols from data for testing purposes
 * @param data - Data to process
 * @returns Data with symbols removed (via JSON parse/stringify)
 */
function stripSymbols<T>(data: T): T;

/**
 * Maybe deep freeze object in development/test environments
 * @param obj - Object to potentially freeze
 * @returns Frozen object in dev/test, original object in production
 */
function maybeDeepFreeze(obj: any): any;

Usage Examples:

import { stripSymbols, maybeDeepFreeze } from "apollo-utilities";

// Strip symbols for testing
const dataWithSymbols = {
  name: "test",
  [Symbol.iterator]: function* () { yield 1; },
  nested: {
    value: 42,
    [Symbol.for("key")]: "symbol-value"
  }
};

const clean = stripSymbols(dataWithSymbols);
console.log(clean); // { name: "test", nested: { value: 42 } }

// Conditional deep freezing
const config = { api: { key: "secret" } };
const frozenConfig = maybeDeepFreeze(config);

// In development/test: throws error when trying to modify
// In production: allows modification
try {
  frozenConfig.api.key = "new-secret";
} catch (error) {
  console.log("Cannot modify frozen object"); // In dev/test only
}

Platform Detection

Utility for detecting platform capabilities.

/**
 * Whether WeakMap can be used safely in current environment
 */
const canUseWeakMap: boolean;

Usage Example:

import { canUseWeakMap } from "apollo-utilities";

// Use WeakMap only if supported and safe
const cache = canUseWeakMap 
  ? new WeakMap() 
  : new Map(); // Fallback to Map

if (canUseWeakMap) {
  console.log("Using WeakMap for caching");
} else {
  console.log("WeakMap not available, using Map fallback");
}

Advanced Type Definition

type TupleToIntersection<T extends any[]> =
  T extends [infer A] ? A :
  T extends [infer A, infer B] ? A & B :
  T extends [infer A, infer B, infer C] ? A & B & C :
  T extends [infer A, infer B, infer C, infer D] ? A & B & C & D :
  T extends [infer A, infer B, infer C, infer D, infer E] ? A & B & C & D & E :
  T extends (infer U)[] ? U : any;