/**
* @archivo middleware.js
* @módulo de software intermedio
* /
importar {asignar} desde '../utils/obj.js';
importar {toTitleCase} desde '../utils/string-cases.js';
const middlewares = {};
const middlewareInstances = {};
exportar const TERMINATOR = {};
/**
* Un objeto de middleware es un objeto simple de JavaScript que tiene métodos que
* haga coincidir los métodos {@link Tech} que se encuentran en las listas de permitidos
* {@módulo de enlace: middleware.allowedGetters|captadores},
* {@link module:middleware.allowedSetters|setters}, y
* {@módulo de enlace:middleware.allowedMediators|mediadores}.
*
* @typedef {Objeto} MiddlewareObject
* /
/**
* Una función de fábrica de middleware que debería devolver un
* {@módulo de enlace:middleware~MiddlewareObject|MiddlewareObject}.
*
* Esta fábrica se llamará para cada jugador cuando sea necesario, con el jugador
* pasado como un argumento.
*
* @callback MiddlewareFactory
* @param {Jugador} jugador
* Un reproductor de Video.js.
* /
/**
* Definir un middleware que el jugador debería usar por medio de una función de fábrica
* que devuelve un objeto de middleware.
*
* @param {cadena} tipo
* El tipo MIME para hacer coincidir o `"*"` para todos los tipos MIME.
*
* @param {MiddlewareFactory} software intermedio
* Una función de fábrica de middleware que se ejecutará para
* tipos coincidentes.
* /
uso de la función de exportación (tipo, middleware) {
middleware[tipo] = middleware[tipo] || [];
middlewares[tipo].push(middleware);
}
/**
* Obtiene middlewares por tipo (o todos los middlewares).
*
* @param {cadena} tipo
* El tipo MIME para hacer coincidir o `"*"` para todos los tipos MIME.
*
* @return {Función[]|indefinido}
* Una matriz de middlewares o `indefinido` si no existe ninguno.
* /
función de exportación getMiddleware (tipo) {
si (tipo) {
volver middlewares[tipo];
}
devolver middlewares;
}
/**
* Establece de forma asincrónica una fuente utilizando middleware recurriendo a través de cualquier
* emparejando middlewares y llamando a `setSource` en cada uno, pasando a lo largo del
* valor devuelto anterior cada vez.
*
* @param {Jugador} jugador
* Una instancia de {@link Player}.
*
* @param {Tech~SourceObject} src
* Un objeto fuente.
*
* @param {Función}
* El próximo middleware a ejecutar.
* /
función de exportación setSource (jugador, src, siguiente) {
jugador.setTimeout(() => setSourceHelper(src, middlewares[src.type], next, player), 1);
}
/**
* Cuando se establece la tecnología, pasa la tecnología al método `setTech` de cada middleware.
*
* @param {Objeto[]} software intermedio
* Una matriz de instancias de middleware.
*
* @param {Tecnología} tecnología
* Una tecnología Video.js.
* /
función de exportación setTech (middleware, tecnología) {
middleware.forEach((mw) => mw.setTech && mw.setTech(tecnología));
}
/**
* Primero llama a un getter en la tecnología, a través de cada middleware
* de derecha a izquierda al jugador.
*
* @param {Objeto[]} software intermedio
* Una matriz de instancias de middleware.
*
* @param {Tecnología} tecnología
* La tecnología actual.
*
* Método @param {cadena}
* Un nombre de método.
*
* @return {Mixto}
* El valor final de la tecnología después de que el middleware la haya interceptado.
* /
función de exportación get (middleware, tecnología, método) {
return middleware.reduceRight(middlewareIterator(método), tech[método]());
}
/**
* Toma el argumento dado al jugador y llama al método setter en cada
* middleware de izquierda a derecha a la tecnología.
*
* @param {Objeto[]} software intermedio
* Una matriz de instancias de middleware.
*
* @param {Tecnología} tecnología
* La tecnología actual.
*
* Método @param {cadena}
* Un nombre de método.
*
* @param {Mixto} argumento
* El valor a establecer en la tecnología.
*
* @return {Mixto}
* El valor de retorno del `método` de la `tecnología`.
* /
conjunto de funciones de exportación (middleware, tecnología, método, argumento) {
return tech[método](middleware.reduce(middlewareIterator(método), arg));
}
/**
* Toma el argumento dado al jugador y llama a la versión `call` del
* método en cada middleware de izquierda a derecha.
*
* Luego, llame al método pasado en la tecnología y devuelva el resultado sin cambios
* de vuelta al jugador, a través del middleware, esta vez de derecha a izquierda.
*
* @param {Objeto[]} software intermedio
* Una matriz de instancias de middleware.
*
* @param {Tecnología} tecnología
* La tecnología actual.
*
* Método @param {cadena}
* Un nombre de método.
*
* @param {Mixto} argumento
* El valor a establecer en la tecnología.
*
* @return {Mixto}
* El valor de retorno del `método` de la `tecnología`, independientemente de la
* valores devueltos de middlewares.
* /
función de exportación mediar (middleware, tecnología, método, arg = null) {
const callMethod = 'llamar' + toTitleCase(método);
const middlewareValue = middleware.reduce(middlewareIterator(callMethod), arg);
const terminado = middlewareValue === TERMINATOR;
// obsoleto. En su lugar, el valor de retorno `nulo` debería devolver TERMINATOR a
// evitar confusiones si un método técnico realmente devuelve nulo.
const returnValue = terminado? nulo: tecnología [método] (middlewareValue);
executeRight(middleware, método, returnValue, terminado);
devolver valor de retorno;
}
/**
* Enumeración de captadores permitidos donde las claves son nombres de métodos.
*
* @type {Objeto}
* /
export const allowGetters = {
amortiguado: 1,
tiempo actual: 1,
duración: 1,
apagado: 1,
jugó: 1,
pausado: 1,
buscable: 1,
volumen: 1,
terminó: 1
};
/**
* Enumeración de setters permitidos donde las claves son nombres de métodos.
*
* @type {Objeto}
* /
exportar const permitidoSetters = {
establecer la hora actual: 1,
establecer silenciado: 1,
establecerVolumen: 1
};
/**
* Enumeración de mediadores permitidos donde las claves son nombres de métodos.
*
* @type {Objeto}
* /
export const allowMediators = {
jugar: 1,
pausa: 1
};
función middlewareIterator(método) {
retorno (valor, mw) => {
// si el middleware anterior terminó, pasar la terminación
si (valor === TERMINADOR) {
volver TERMINADOR;
}
if (mw[método]) {
return mw[método](valor);
}
valor de retorno;
};
}
función ejecutarDerecho(mws, método, valor, terminado) {
para (sea i = mws.length - 1; i > = 0; i--) {
const mw = mws[i];
if (mw[método]) {
mw[método](terminado, valor);
}
}
}
/**
* Borrar la memoria caché de middleware para un jugador.
*
* @param {Jugador} jugador
* Una instancia de {@link Player}.
* /
función de exportación clearCacheForPlayer (jugador) {
middlewareInstances[player.id()] = null;
}
/**
* {
* [IdJugador]: [[mwFactory, mwInstance], ...]
* }
*
* @privado
* /
función getOrCreateFactory(jugador, mwFactory) {
const mws = middlewareInstances[player.id()];
sea mw = nulo;
if (mws === indefinido || mws === nulo) {
mw = mwFactory(jugador);
middlewareInstances[player.id()] = [[mwFactory, mw]];
volver mw;
}
para (sea i = 0; i < mws.longitud; i++) {
constante [mwf, mwi] = mws[i];
if (mwf !== mwFábrica) {
continuar;
}
mw = mwi;
}
si (mw === nulo) {
mw = mwFactory(jugador);
mws.push([mwFábrica, mw]);
}
volver mw;
}
function setSourceHelper(src = {}, middleware = [], next, player, acc = [], lastRun = false) {
const [mwFactory, ...mwrest] = middleware;
// si mwFactory es una cadena, entonces estamos en una bifurcación en el camino
if (tipo de mwFactory === 'cadena') {
setSourceHelper(src, middlewares[mwFactory], next, player, acc, lastRun);
// si tenemos un mwFactory, llamalo con el jugador para obtener el mw,
// luego llamar al método setSource de mw
} si no (mwFactory) {
const mw = getOrCreateFactory(jugador, mwFactory);
// si setSource no está presente, seleccione implícitamente este middleware
if (!mw.setFuente) {
acc.pulsar(mw);
return setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
mw.setSource(asignar({}, src), función(err, _src) {
// algo sucedió, pruebe el siguiente middleware en el nivel actual
// asegúrese de usar el antiguo src
si (err) {
return setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
// lo hemos logrado, ahora debemos profundizar más
acc.pulsar(mw);
// si es del mismo tipo, continúa hacia abajo en la cadena actual
// de lo contrario, queremos bajar por la nueva cadena
setSourceHelper(
_src,
src.tipo === _src.tipo ? mwrest : middleware[_src.type],
próximo,
jugador,
según,
última carrera
);
});
} else if (mwrest.longitud) {
setSourceHelper(src, mwrest, next, player, acc, lastRun);
} más si (última Ejecución) {
siguiente(fuente, acc);
} else {
setSourceHelper(src, middlewares['*'], next, player, acc, true);
}
}