<commit_before>import { Meteor } from 'meteor/meteor';
import * as _ from 'underscore';

import { debug } from './debug';
import { Utils } from './utils';

/**
 * @summary Format callback hook names
 */
const formatHookName = (hook: string|null): string => hook?.toLowerCase() || "";

/**
 * @summary A list of all registered callback hooks
 */
const CallbackHooks: Array<any> = [];

/**
 * @summary Callback hooks provide an easy way to add extra steps to common operations.
 * @namespace Callbacks
 */
const Callbacks: Record<string,any> = {};


/**
 * @summary Register a callback
 * @param {String} hook - The name of the hook
 * @param {Function} callback - The callback function
 */
export const registerCallback = function (callback) {
  CallbackHooks.push(callback);
};

/**
 * @summary Add a callback function to a hook
 * @param {String} hook - The name of the hook
 * @param {Function} callback - The callback function
 */
export const addCallback = function (hook, callback) {

  const formattedHook = formatHookName(hook);

  // if callback array doesn't exist yet, initialize it
  if (typeof Callbacks[formattedHook] === 'undefined') {
    Callbacks[formattedHook] = [];
  }

  Callbacks[formattedHook].push(callback);
  
  if (Callbacks[formattedHook].length > 10) {
    // eslint-disable-next-line no-console
    console.log(`Warning: Excessively many hooks (${Callbacks[formattedHook].length}) on callback ${callback}.`);
  }
  
  return callback;
};

/**
 * @summary Remove a callback from a hook
 * @param {string} hookName - The name of the hook
 * @param {Function} callback - A reference to the function which was previously
 *   passed to addCallback.
 */
export const removeCallback = function (hookName, callback) {
  const formattedHook = formatHookName(hookName);
  Callbacks[formattedHook] = _.reject(Callbacks[formattedHook],
    c => c === callback
  );
};

/**
 * @summary Successively run all of a hook's callbacks on an item
 * @param {String} hook - First argument: the name of the hook, or an array
 * @param {Object} item - Second argument: the post, comment, modifier, etc. on which to run the callbacks
 * @param {Any} args - Other arguments will be passed to each successive iteration
 * @param {Array} callbacks - Optionally, pass an array of callback functions instead of passing a hook name
 * @param {Boolean} ignoreExceptions - Only available as a named argument, default true. If true, exceptions
 *   thrown from callbacks will be logged but otherwise ignored. If false, exceptions thrown from callbacks
 *   will be rethrown.
 * @returns {Object} Returns the item after it's been through all the callbacks for this hook
 */<commit_msg>Fix a weird console warning on server startup<commit_after>import { Meteor } from 'meteor/meteor';
import * as _ from 'underscore';

import { debug } from './debug';
import { Utils } from './utils';

/**
 * @summary Format callback hook names
 */
const formatHookName = (hook: string|null): string => hook?.toLowerCase() || "";

/**
 * @summary A list of all registered callback hooks
 */
const CallbackHooks: Array<any> = [];

/**
 * @summary Callback hooks provide an easy way to add extra steps to common operations.
 * @namespace Callbacks
 */
const Callbacks: Record<string,any> = {};


/**
 * @summary Register a callback
 * @param {String} hook - The name of the hook
 * @param {Function} callback - The callback function
 */
export const registerCallback = function (callback) {
  CallbackHooks.push(callback);
};

/**
 * @summary Add a callback function to a hook
 * @param {String} hook - The name of the hook
 * @param {Function} callback - The callback function
 */
export const addCallback = function (hook, callback) {

  const formattedHook = formatHookName(hook);

  // if callback array doesn't exist yet, initialize it
  if (typeof Callbacks[formattedHook] === 'undefined') {
    Callbacks[formattedHook] = [];
  }

  Callbacks[formattedHook].push(callback);
  
  if (Callbacks[formattedHook].length > 15) {
    // eslint-disable-next-line no-console
    console.log(`Warning: Excessively many hooks (${Callbacks[formattedHook].length}) on callback ${formattedHook}.`);
  }
  
  return callback;
};

/**
 * @summary Remove a callback from a hook
 * @param {string} hookName - The name of the hook
 * @param {Function} callback - A reference to the function which was previously
 *   passed to addCallback.
 */
export const removeCallback = function (hookName, callback) {
  const formattedHook = formatHookName(hookName);
  Callbacks[formattedHook] = _.reject(Callbacks[formattedHook],
    c => c === callback
  );
};

/**
 * @summary Successively run all of a hook's callbacks on an item
 * @param {String} hook - First argument: the name of the hook, or an array
 * @param {Object} item - Second argument: the post, comment, modifier, etc. on which to run the callbacks
 * @param {Any} args - Other arguments will be passed to each successive iteration
 * @param {Array} callbacks - Optionally, pass an array of callback functions instead of passing a hook name
 * @param {Boolean} ignoreExceptions - Only available as a named argument, default true. If true, exceptions
 *   thrown from callbacks will be logged but otherwise ignored. If false, exceptions thrown from callbacks
 *   will be rethrown.
 * @returns {Object} Returns the item after it's been through all the callbacks for this hook
 */
{'fraction_non_alphanumeric': 0.11034993519718571, 'fraction_numerical': 0.0007406035919274209, 'mean_word_length': 4.029795158286778, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '125890', 'n_tokens_mistral': 1490, 'n_tokens_neox': 1461, 'n_words': 605}