mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-30 17:37:26 +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; |