<commit_before>import {
    createExtensionsValidator,
    validateAdapter,
    validateArgs,
    validateCreateExtensionsMethod,
    validateExtra,
    validateHook,
    validateHooks,
    validateMethodName,
    validatePlugins
} from './validation';
import requiredMethods from './requiredMethods';

function upperFirst(string) {
    const firstLetter = string[0];
    const restOfTheString = string.substr(1);

    return `${firstLetter.toUpperCase()}${restOfTheString}`;
}

function passDataThroughEventHandlers(eventHandlers, args) {
    return eventHandlers.reduce(async (previousValue, handler) => {
        return await handler(await previousValue);
    }, args);
}

function passDataThroughHooks(hooks, event, args) {
    const eventHandlers = hooks[event];
    const resolvedArgs = Promise.resolve(args);

    return Array.isArray(eventHandlers) ? passDataThroughEventHandlers(eventHandlers, resolvedArgs) : resolvedArgs;
}

export function emit(eventName, args) {
    validateArgs(args);

    const hooks = args.cacheInstance.getHooks();

    return passDataThroughHooks(hooks, eventName, args);
}

const getData = (prefix, methodName, args) => {
    validateMethodName(methodName);
    validateArgs(args);

    const hooks = args.cacheInstance.getHooks();
    const event = `${prefix}${upperFirst(methodName)}`;

    return passDataThroughHooks(hooks, event, args);
};

export const getPreData = (methodName, args) => getData('pre', methodName, args);
export const getPostData = (methodName, args) => getData('post', methodName, args);

function cloneHooks(hooks) {
    const cloned = {};

    Object.entries(hooks).forEach(([ event, handlers ]) => {
        cloned[event] = handlers.map((handler) => handler);
    });

    return cloned;
}

export function createCache(adapter) {
    validateAdapter(adapter, requiredMethods);

    const cacheInstance = {
        hooks: {},

        addHook(hook) {
            validateHook(hook);

            const { event, handler } = hook;

            this.hooks[event] ? this.hooks[event].push(handler) : (this.hooks[event] = [handler]);
        },

        addHooks(hooks) {
            validateHooks(hooks);

            hooks.forEach(this.addHook.bind(this));
        },

        getHooks() {
            return this.hooks;
        },

        async buildKey(key) {
            const preData = await getPreData('buildKey', { cacheInstance: this, key });
            const builtKey = await adapter.buildKey(preData.key);
            const postData = await getPostData('buildKey', { cacheInstance: preData.cacheInstance, key: builtKey });

            return postData.key;
        },

        getItem(key) {
            const preData = getPreData('getItem', { cacheInstance: this, key });
            const item = adapter.getItem(this.buildKey(preData.key));
            const postData = getPostData('getItem', { cacheInstance: preData.cacheInstance, key: preData.key, item });

            return postData.item;
        },

        getExtra(key) {
            const preData = getPreData('getExtra', { cacheInstance: this, key });
            const extra = adapter.getExtra(this.buildKey(preData.key));
            const postData = getPostData('getExtra', { cacheInstance: preData.cacheInstance, key: preData.key, extra });

            return postData.extra;<commit_msg>Use emit function instead of getPreData and getPostData<commit_after>import {
    createExtensionsValidator,
    validateAdapter,
    validateArgs,
    validateCreateExtensionsMethod,
    validateExtra,
    validateHook,
    validateHooks,
    validateMethodName,
    validatePlugins
} from './validation';
import requiredMethods from './requiredMethods';

function upperFirst(string) {
    const firstLetter = string[0];
    const restOfTheString = string.substr(1);

    return `${firstLetter.toUpperCase()}${restOfTheString}`;
}

function passDataThroughEventHandlers(eventHandlers, args) {
    return eventHandlers.reduce(async (previousValue, handler) => {
        return await handler(await previousValue);
    }, args);
}

function passDataThroughHooks(hooks, event, args) {
    const eventHandlers = hooks[event];
    const resolvedArgs = Promise.resolve(args);

    return Array.isArray(eventHandlers) ? passDataThroughEventHandlers(eventHandlers, resolvedArgs) : resolvedArgs;
}

export function emit(eventName, args) {
    validateArgs(args);

    const hooks = args.cacheInstance.getHooks();

    return passDataThroughHooks(hooks, eventName, args);
}

const getData = (prefix, methodName, args) => {
    validateMethodName(methodName);
    validateArgs(args);

    const hooks = args.cacheInstance.getHooks();
    const event = `${prefix}${upperFirst(methodName)}`;

    return passDataThroughHooks(hooks, event, args);
};

export const getPreData = (methodName, args) => getData('pre', methodName, args);
export const getPostData = (methodName, args) => getData('post', methodName, args);

function cloneHooks(hooks) {
    const cloned = {};

    Object.entries(hooks).forEach(([ event, handlers ]) => {
        cloned[event] = handlers.map((handler) => handler);
    });

    return cloned;
}

export function createCache(adapter) {
    validateAdapter(adapter, requiredMethods);

    const cacheInstance = {
        hooks: {},

        addHook(hook) {
            validateHook(hook);

            const { event, handler } = hook;

            this.hooks[event] ? this.hooks[event].push(handler) : (this.hooks[event] = [handler]);
        },

        addHooks(hooks) {
            validateHooks(hooks);

            hooks.forEach(this.addHook.bind(this));
        },

        getHooks() {
            return this.hooks;
        },

        async buildKey(key) {
            const preData = await emit('preBuildKey', { cacheInstance: this, key });
            const builtKey = await adapter.buildKey(preData.key);
            const postData = await emit('postBuildKey', { cacheInstance: preData.cacheInstance, key: builtKey });

            return postData.key;
        },

        getItem(key) {
            const preData = getPreData('getItem', { cacheInstance: this, key });
            const item = adapter.getItem(this.buildKey(preData.key));
            const postData = getPostData('getItem', { cacheInstance: preData.cacheInstance, key: preData.key, item });

            return postData.item;
        },

        getExtra(key) {
            const preData = getPreData('getExtra', { cacheInstance: this, key });
            const extra = adapter.getExtra(this.buildKey(preData.key));
            const postData = getPostData('getExtra', { cacheInstance: preData.cacheInstance, key: preData.key, extra });

            return postData.extra;
{'fraction_non_alphanumeric': 0.11961722488038277, 'fraction_numerical': 0.0005980861244019139, 'mean_word_length': 3.1650062266500623, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '1633710', 'n_tokens_mistral': 1880, 'n_tokens_neox': 1856, 'n_words': 400}