mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	
		
			
	
	
		
			133 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			133 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const { cloneDeep } = require('lodash/fp');
							 | 
						||
| 
								 | 
							
								const { createAsyncSeriesHook, createAsyncParallelHook } = require('./hooks');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @typedef ProviderHooksMap
							 | 
						||
| 
								 | 
							
								 * @property willRegister
							 | 
						||
| 
								 | 
							
								 * @property didRegister
							 | 
						||
| 
								 | 
							
								 * @property willDelete
							 | 
						||
| 
								 | 
							
								 * @property didDelete
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Creates a new object containing various hooks used by the providers
							 | 
						||
| 
								 | 
							
								 * @return {ProviderHooksMap}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								const createProviderHooksMap = () => ({
							 | 
						||
| 
								 | 
							
								  // Register events
							 | 
						||
| 
								 | 
							
								  willRegister: createAsyncSeriesHook(),
							 | 
						||
| 
								 | 
							
								  didRegister: createAsyncParallelHook(),
							 | 
						||
| 
								 | 
							
								  // Delete events
							 | 
						||
| 
								 | 
							
								  willDelete: createAsyncParallelHook(),
							 | 
						||
| 
								 | 
							
								  didDelete: createAsyncParallelHook(),
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * A customizable item provider enhanced with register/delete hooks
							 | 
						||
| 
								 | 
							
								 * @typedef {Object} Provider
							 | 
						||
| 
								 | 
							
								 * @property hooks
							 | 
						||
| 
								 | 
							
								 * @property register
							 | 
						||
| 
								 | 
							
								 * @property delete
							 | 
						||
| 
								 | 
							
								 * @property get
							 | 
						||
| 
								 | 
							
								 * @property getWhere
							 | 
						||
| 
								 | 
							
								 * @property values
							 | 
						||
| 
								 | 
							
								 * @property keys
							 | 
						||
| 
								 | 
							
								 * @property has
							 | 
						||
| 
								 | 
							
								 * @property size
							 | 
						||
| 
								 | 
							
								 * @property clear
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * A {@link Provider} factory
							 | 
						||
| 
								 | 
							
								 * @param {Object} [options] - The factory options
							 | 
						||
| 
								 | 
							
								 * @param {boolean = true} options.throwOnDuplicates - Specify the wanted behaviour when encountering a duplicate key on register
							 | 
						||
| 
								 | 
							
								 * @return {Provider}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								const providerFactory = (options = {}) => {
							 | 
						||
| 
								 | 
							
								  const { throwOnDuplicates = true } = options;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const state = {
							 | 
						||
| 
								 | 
							
								    hooks: createProviderHooksMap(),
							 | 
						||
| 
								 | 
							
								    registry: new Map(),
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return {
							 | 
						||
| 
								 | 
							
								    hooks: state.hooks,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async register(key, item) {
							 | 
						||
| 
								 | 
							
								      if (throwOnDuplicates && this.has(key)) {
							 | 
						||
| 
								 | 
							
								        throw new Error(`Duplicated item key: ${key}`);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      await state.hooks.willRegister.call({ key, value: item });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      state.registry.set(key, item);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      await state.hooks.didRegister.call({ key, value: cloneDeep(item) });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return this;
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async delete(key) {
							 | 
						||
| 
								 | 
							
								      if (this.has(key)) {
							 | 
						||
| 
								 | 
							
								        const item = this.get(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        await state.hooks.willDelete.call({ key, value: cloneDeep(item) });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        state.registry.delete(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        await state.hooks.didDelete.call({ key, value: cloneDeep(item) });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return this;
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    get(key) {
							 | 
						||
| 
								 | 
							
								      return state.registry.get(key);
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    getWhere(filters = {}) {
							 | 
						||
| 
								 | 
							
								      const items = this.values();
							 | 
						||
| 
								 | 
							
								      const filtersEntries = Object.entries(filters);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (filtersEntries.length === 0) {
							 | 
						||
| 
								 | 
							
								        return items;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return items.filter(item => {
							 | 
						||
| 
								 | 
							
								        return filtersEntries.every(([key, value]) => item[key] === value);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    values() {
							 | 
						||
| 
								 | 
							
								      return Array.from(state.registry.values());
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    keys() {
							 | 
						||
| 
								 | 
							
								      return Array.from(state.registry.keys());
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    has(key) {
							 | 
						||
| 
								 | 
							
								      return state.registry.has(key);
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    size() {
							 | 
						||
| 
								 | 
							
								      return state.registry.size;
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    async clear() {
							 | 
						||
| 
								 | 
							
								      const keys = this.keys();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (const key of keys) {
							 | 
						||
| 
								 | 
							
								        await this.delete(key);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return this;
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = providerFactory;
							 |