General purpose node utilities providing object manipulation, array operations, string utilities, data validation, async utilities, and path operations for the hapi ecosystem.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Function wrapper utilities for controlling execution patterns and providing no-op functionality in various programming contexts.
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 receivedA 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 callbacksImportant Notes:
once does NOT preserve the original function's return type - all calls return undefinedonce is thread-safe and handles concurrent calls correctlyignore is a constant function reference, making it efficient for repeated use