CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hapi--hoek

General purpose node utilities providing object manipulation, array operations, string utilities, data validation, async utilities, and path operations for the hapi ecosystem.

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

function-utilities.mddocs/

Function Utilities

Function wrapper utilities for controlling execution patterns and providing no-op functionality in various programming contexts.

Capabilities

Once

Wraps a function to ensure it can only execute once. The wrapped function does not return the result of the original function and subsequent calls do nothing.

/**
 * Wraps a function to ensure it can only execute once
 * @param method - The function to be wrapped
 * @returns A wrapped function that executes the method once and returns undefined on all calls
 */
function once<T extends Function>(method: T): (...args: any[]) => void;

Usage Examples:

import { once } from "@hapi/hoek";

// Basic usage
const myFunction = () => {
  console.log('This will only run once');
  return 'result';
};

const onceFunction = once(myFunction);
const result1 = onceFunction(); // Logs message, returns undefined
const result2 = onceFunction(); // Returns undefined, no log
const result3 = onceFunction(); // Returns undefined, no log

// Initialization function
const initializeApp = once(() => {
  console.log('Initializing application...');
  // Setup code here
  return { initialized: true };
});

// Safe to call multiple times
initializeApp(); // Runs initialization, returns undefined
initializeApp(); // Does nothing, returns undefined
initializeApp(); // Does nothing, returns undefined

// Event handler that should only run once
const handleFirstClick = once((event: Event) => {
  console.log('First click detected!');
  // Setup one-time behavior
});

button.addEventListener('click', handleFirstClick);
// First click triggers the handler, subsequent clicks do nothing

// Async function wrapping
const fetchUserOnce = once(async (userId: string) => {
  console.log(`Fetching user ${userId}...`);
  const response = await fetch(`/api/users/${userId}`);
  return response.json();
});

// Multiple calls, but only first one executes
const user1 = await fetchUserOnce('123'); // Fetches user, returns undefined
const user2 = await fetchUserOnce('123'); // Returns undefined
const user3 = await fetchUserOnce('456'); // Returns undefined (still same wrapped function)

// Constructor or factory function
const createSingleton = once(() => {
  return {
    id: Math.random(),
    createdAt: new Date(),
    // singleton properties
  };
});

const singleton1 = createSingleton(); // Creates instance, returns undefined
const singleton2 = createSingleton(); // Returns undefined
// Note: The created instance is not returned, you need a different pattern for singletons

// Method wrapping with context preservation
class Logger {
  private setupDone = false;
  
  constructor() {
    this.setup = once(this.setup.bind(this));
  }
  
  setup() {
    console.log('Setting up logger...');
    this.setupDone = true;
  }
  
  log(message: string) {
    this.setup(); // Safe to call multiple times
    if (this.setupDone) {
      console.log(message);
    }
  }
}

// Cleanup or teardown functions
const cleanup = once(() => {
  console.log('Cleaning up resources...');
  // Cleanup code that should only run once
});

process.on('exit', cleanup);
process.on('SIGINT', cleanup);
process.on('SIGTERM', cleanup);
// Cleanup will only run once regardless of which signal is received

Ignore

A reusable no-op function that accepts any arguments and returns undefined.

/**
 * A reusable no-op function
 * @param args - Any number of arguments (all ignored)
 * @returns undefined
 */
function ignore(...args: any): void;

Usage Examples:

import { ignore } from "@hapi/hoek";

// Default callback parameter
function processData(data: any[], callback = ignore) {
  // Process data
  for (const item of data) {
    // Do processing
  }
  callback(null, data); // Safe to call even if no callback provided
}

// Usage without callback
processData([1, 2, 3]); // Works fine, ignore handles the callback

// Promise.catch() placeholder
Promise.resolve('success')
  .then(result => console.log(result))
  .catch(ignore); // Silently ignore errors

// Event handler placeholder
const button = document.getElementById('myButton');
button?.addEventListener('click', ignore); // No-op click handler

// Optional error handling
function riskyOperation(onError = ignore) {
  try {
    // Some risky operation
    throw new Error('Something went wrong');
  } catch (error) {
    onError(error); // Safe to call even if onError is not provided
  }
}

// Array methods with placeholder functions
const data = [1, 2, 3, 4, 5];

// Placeholder for unused array callback parameters
const processedData = data.map((value, index, array) => {
  ignore(index, array); // Explicitly ignore unused parameters
  return value * 2;
});

// Stream or event emitter placeholder
const stream = new EventEmitter();
stream.on('data', ignore); // Ignore data events
stream.on('error', ignore); // Ignore error events

// Testing or development placeholder
const api = {
  development: {
    log: console.log,
    error: console.error
  },
  production: {
    log: ignore, // Disable logging in production
    error: console.error
  }
};

const logger = process.env.NODE_ENV === 'production' 
  ? api.production 
  : api.development;

logger.log('This may or may not appear');

// Conditional function execution
const debugMode = false;
const debugLog = debugMode ? console.log : ignore;

debugLog('Debug message'); // Only logs if debugMode is true

// Placeholder in function composition
const pipeline = [
  processStep1,
  processStep2,
  debugMode ? logStep : ignore,
  processStep3
];

// Clean way to handle optional operations
function setupApplication(onProgress = ignore, onComplete = ignore) {
  onProgress('Starting setup...');
  // Setup steps
  onProgress('Installing dependencies...');
  // More setup
  onComplete('Setup completed');
}

// Can call with or without callbacks
setupApplication(); // Works fine
setupApplication(console.log); // With progress logging
setupApplication(console.log, () => console.log('Done!')); // With both callbacks

Important Notes:

  • once does NOT preserve the original function's return type - all calls return undefined
  • The wrapped function executes the original function once but does not return its result
  • once is thread-safe and handles concurrent calls correctly
  • ignore is a constant function reference, making it efficient for repeated use
  • Both utilities are commonly used in callback patterns and optional parameter scenarios
  • Perfect for cleanup functions, initialization routines, and placeholder callbacks

docs

array-operations.md

async-promise-utilities.md

data-utilities.md

function-utilities.md

index.md

object-operations.md

path-operations.md

performance-benchmarking.md

string-utilities.md

validation-assertions.md

tile.json