bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
193 lines (164 loc) • 4.81 kB
JavaScript
/**
* Middleware Registry
*
* Centralized system for registering and composing middleware functions
* @module middleware/MiddlewareRegistry
*/
/**
* @class MiddlewareRegistry
* @description Registry for middleware functions with composition utilities
*/
class MiddlewareRegistry {
/**
* Create a new middleware registry
*/
constructor() {
this.middleware = new Map();
}
/**
* Register middleware for a specific category
* @param {string} category - Middleware category
* @param {string} name - Middleware name
* @param {Function} fn - Middleware function
* @returns {MiddlewareRegistry} Registry instance for chaining
*/
register(category, name, fn) {
if (!this.middleware.has(category)) {
this.middleware.set(category, new Map());
}
this.middleware.get(category).set(name, fn);
return this;
}
/**
* Get middleware by name
* @param {string} category - Middleware category
* @param {string} name - Middleware name
* @returns {Function|null} Middleware function or null if not found
*/
get(category, name) {
if (!this.middleware.has(category)) {
return null;
}
return this.middleware.get(category).get(name) || null;
}
/**
* Get all middleware for a category
* @param {string} category - Middleware category
* @returns {Map<string, Function>} Map of middleware functions
*/
getCategory(category) {
return this.middleware.get(category) || new Map();
}
/**
* Check if middleware exists
* @param {string} category - Middleware category
* @param {string} name - Middleware name
* @returns {boolean} True if middleware exists
*/
has(category, name) {
if (!this.middleware.has(category)) {
return false;
}
return this.middleware.get(category).has(name);
}
/**
* List all middleware names for a category
* @param {string} category - Middleware category
* @returns {Array<string>} List of middleware names
*/
list(category) {
if (!this.middleware.has(category)) {
return [];
}
return Array.from(this.middleware.get(category).keys());
}
/**
* List all categories
* @returns {Array<string>} List of categories
*/
listCategories() {
return Array.from(this.middleware.keys());
}
/**
* Create a middleware chain from a list of middleware names
* @param {string} category - Middleware category
* @param {Array<string|Function>} names - Middleware names or functions
* @returns {Function} Composed middleware function
*/
createChain(category, names) {
const middlewareFns = names.map(name => {
if (typeof name === 'function') {
return name;
}
const fn = this.get(category, name);
if (!fn) {
throw new Error(`Middleware not found: ${category}/${name}`);
}
return fn;
});
return compose(middlewareFns);
}
}
/**
* Compose middleware functions into a single function
* @param {Array<Function>} middleware - Middleware functions
* @returns {Function} Composed middleware function
*/
function compose(middleware) {
return async (context, next) => {
// Last called middleware
let index = -1;
async function dispatch(i) {
if (i <= index) {
throw new Error('next() called multiple times');
}
index = i;
let fn = middleware[i];
if (i === middleware.length) {
fn = next;
}
if (!fn) {
return;
}
return fn(context, dispatch.bind(null, i + 1));
}
return dispatch(0);
};
}
/**
* Create a middleware function that combines functions in sequence
* @param {...Function} fns - Functions to combine
* @returns {Function} Combined function
*/
function sequence(...fns) {
return async (input, context) => {
let result = input;
for (const fn of fns) {
result = await fn(result, context);
}
return result;
};
}
/**
* Create a conditional middleware function
* @param {Function} condition - Condition function
* @param {Function} middleware - Middleware function
* @returns {Function} Conditional middleware function
*/
function conditional(condition, middleware) {
return async (input, context) => {
if (await condition(input, context)) {
return middleware(input, context);
}
return input;
};
}
// Create default registry instance
const defaultRegistry = new MiddlewareRegistry();
module.exports = {
MiddlewareRegistry,
defaultRegistry,
compose,
sequence,
conditional
};