mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 09:56:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			100 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| const { eq, remove, cloneDeep } = require('lodash/fp');
 | |
| 
 | |
| /**
 | |
|  * @typedef Hook
 | |
|  * @property {Array<Function>} _handlers - A registry of handler used by the hook
 | |
|  * @property {function(Function):Hook} register - Register a new handler into the hook's registry
 | |
|  * @property {function(Function):Hook} delete- Delete the given handler from the hook's registry
 | |
|  * @property {Function} call - Not implemented by default, can be replaced by any implementation.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Create a default Strapi hook
 | |
|  * @return {Hook}
 | |
|  */
 | |
| const createHook = () => {
 | |
|   const state = {
 | |
|     handlers: [],
 | |
|   };
 | |
| 
 | |
|   return {
 | |
|     get handlers() {
 | |
|       return state.handlers;
 | |
|     },
 | |
| 
 | |
|     register: handler => {
 | |
|       state.handlers.push(handler);
 | |
|     },
 | |
| 
 | |
|     delete: handler => {
 | |
|       state.handlers = remove(eq(handler), state.handlers);
 | |
|     },
 | |
| 
 | |
|     call() {
 | |
|       throw new Error('Method not implemented');
 | |
|     },
 | |
|   };
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Create an async series hook.
 | |
|  * Upon execution, it will execute every handler in order with the same context
 | |
|  * @return {Hook}
 | |
|  */
 | |
| const createAsyncSeriesHook = () => ({
 | |
|   ...createHook(),
 | |
| 
 | |
|   async call(context) {
 | |
|     for (const handler of this.handlers) {
 | |
|       await handler(context);
 | |
|     }
 | |
|   },
 | |
| });
 | |
| 
 | |
| /**
 | |
|  * Create an async series waterfall hook.
 | |
|  * Upon execution, it will execute every handler in order and pass the return value of the last handler to the next one
 | |
|  * @return {Hook}
 | |
|  */
 | |
| const createAsyncSeriesWaterfallHook = () => ({
 | |
|   ...createHook(),
 | |
| 
 | |
|   async call(param) {
 | |
|     let res = param;
 | |
| 
 | |
|     for (const handler of this.handlers) {
 | |
|       res = await handler(res);
 | |
|     }
 | |
| 
 | |
|     return res;
 | |
|   },
 | |
| });
 | |
| 
 | |
| /**
 | |
|  * Create an async parallel hook.
 | |
|  * Upon execution, it will execute every registered handler in band.
 | |
|  * @return {Hook}
 | |
|  */
 | |
| const createAsyncParallelHook = () => ({
 | |
|   ...createHook(),
 | |
| 
 | |
|   call(context) {
 | |
|     const promises = this.handlers.map(handler => handler(cloneDeep(context)));
 | |
| 
 | |
|     return Promise.all(promises);
 | |
|   },
 | |
| });
 | |
| 
 | |
| module.exports = {
 | |
|   // Internal utils
 | |
|   internals: {
 | |
|     createHook,
 | |
|   },
 | |
|   // Hooks
 | |
|   createAsyncSeriesHook,
 | |
|   createAsyncSeriesWaterfallHook,
 | |
|   createAsyncParallelHook,
 | |
| };
 | 
