UNPKG

@tvkitchen/countertop

Version:

The entry point for developers who want to set up a TV Kitchen.

201 lines (153 loc) 8.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pruneStreams = exports.identifyObsoleteStreams = exports.getStreamTopic = exports.generateTributaryMaps = exports.getSourcesFromStreamMap = exports.getStreamsFromStreamMap = exports.getSourcesFromStreams = exports.getStreamOutputMap = exports.filterStreamsContainingStream = exports.filterStreamsContainingStation = exports.getStreamsThatProduceTypes = exports.getStationsThatConsumeTypes = exports.getCollectiveOutputTypes = exports.getLongestStreamLength = exports.getSourceStations = void 0; var _ = require("."); var _kafka = require("./kafka"); /** * Returns a list of stations that are considered sources. * * The only way a station can currently be a source is if it has no inputs. * This definition may expand over time. * * @param {CountertopStation[]} stations The stations being processed. * @return {CountertopStation[]} The source stations. */ const getSourceStations = stations => stations.filter(station => station.getInputTypes().length === 0); /** * Returns the length (number of stations) of the longest CountertopStream in a set * of CountertopStreams. * * @param {CountertopStream[]} streams The streams being processed. * @return {Number} The longest length. */ exports.getSourceStations = getSourceStations; const getLongestStreamLength = streams => Math.max(...streams.map(stream => stream.getLength()), 0); /** * Returns a list of any type produced by any stream in the set. * * @param {CountertopStream[]} streams The CountertopStreams being processed. * @return {String[]} The types produced by any of those CountertopStreams. */ exports.getLongestStreamLength = getLongestStreamLength; const getCollectiveOutputTypes = streams => [...new Set(streams.flatMap(stream => stream.getOutputTypes()))]; /** * Returns a subset of stations that consume any of the specified types * * @param {CountertopStation[]} stations The array of stations to search. * @param {String[]} types The types that are being searched for. * @return {CountertopStation[]} The filtered array of stations */ exports.getCollectiveOutputTypes = getCollectiveOutputTypes; const getStationsThatConsumeTypes = (stations, types) => stations.filter(station => (0, _.arraysHaveOverlap)(station.getInputTypes(), types)); /** * Returns a subset of streams that produce any of the specified types. * * @param {CountertopStream[]} streams The array of streams to search. * @param {String[]} types The types that are being searched for. * @return {CountertopStream[]} The filtered array of streams */ exports.getStationsThatConsumeTypes = getStationsThatConsumeTypes; const getStreamsThatProduceTypes = (streams, types) => streams.filter(stream => (0, _.arraysHaveOverlap)(stream.getOutputTypes(), types)); /** * Returns a subset of streams that do not contain a given station. * * @param {CountertopStream[]} streams The array of streams to search. * @param {CountertopStation} station The station being filtered out. * @return {CountertopStream[]} The filtered array of streams. */ exports.getStreamsThatProduceTypes = getStreamsThatProduceTypes; const filterStreamsContainingStation = (streams, station) => streams.filter(stream => !stream.includesStation(station)); /** * Returns a subset of streams that do not contain a given stream. * Note that this will also filter the stream itself. * @param {CountertopStream[]} streams * @param {CountertopStream} filteredStream * @returns {CountertopStream[]} */ exports.filterStreamsContainingStation = filterStreamsContainingStation; const filterStreamsContainingStream = (streams, filteredStream) => streams.filter(stream => !stream.includesStream(filteredStream) && stream !== filteredStream); /** * Generates a Map of type / stream[] pairs based on streams who output the types. * * @param {CountertopStream[]} streams The CountertopStreams being mapped. * @return {Map} The resulting map of types => streams */ exports.filterStreamsContainingStream = filterStreamsContainingStream; const getStreamOutputMap = streams => new Map(getCollectiveOutputTypes(streams).map(type => [type, getStreamsThatProduceTypes(streams, [type])])); /** * Get an array of distinct sources reflected inside of an Array of streams. * * This will return exactly one copy of any source represented in those streams. * * @param {CountetopStream[]} streams An array ofstreams * @return {CountertopStation[]} An array of distinct sources for the streams. */ exports.getStreamOutputMap = getStreamOutputMap; const getSourcesFromStreams = streams => [...new Set(streams.map(stream => stream.getSource()))]; /** * Get an array of unique streams represented in a map of streams. * * @param {Map<CountertopStream[]>} streamMap The stream map to be processed. * @return {CountertopStream[]} The unique streams contained in the map. */ exports.getSourcesFromStreams = getSourcesFromStreams; const getStreamsFromStreamMap = streamMap => [...new Set([...streamMap.values()].flat())]; /** * Get an array of distinct sources reflected inside of a stream Map. * * This will return exactly one copy of any source represented in those streams. * * @param {Map<CountetopStream[]>} streamMap A Map containing streams * @return {CountertopStation[]} An array of distinct sources for the streams. */ exports.getStreamsFromStreamMap = getStreamsFromStreamMap; const getSourcesFromStreamMap = streamMap => getSourcesFromStreams(getStreamsFromStreamMap(streamMap)); /** * Create all sets of valid stream combinations that can sufficiently fulfill a set of inputs * * This will only create combinations of streams that pull from the same source. * This will not return incomplete tributary maps (i.e. tributary maps will have exactly one stream * per input). * * @param {CountertopStation} station The station whose tributaries are being mapped. * @param {Map<CountertopStream[]>} streamOutputMap A map of of streams grouped by output type. * @return {Map<CountertopStream>[]} A map of tributary streams for a set of inputs. */ exports.getSourcesFromStreamMap = getSourcesFromStreamMap; const generateTributaryMaps = (station, streamOutputMap) => { const sources = getSourcesFromStreamMap(streamOutputMap); const tributarySeeds = sources.map(source => new Map([['source', source]])); const inputTypes = station.getInputTypes(); return inputTypes.reduce((accumulator, type) => accumulator.flatMap(tributarySet => { const expandedTributarySets = (streamOutputMap.get(type) || []).filter(stream => stream.getSource() === tributarySet.get('source')).map(stream => tributarySet.set(type, stream)); return expandedTributarySets.length > 0 ? expandedTributarySets : [tributarySet]; }), tributarySeeds).map(tributarySet => { tributarySet.delete('source'); // 'source' was an internal helper field return tributarySet; }); }; /** * Returns the kafka topic associated with a given stream + type pair. * * @param {String} dataType The data type. * @param {CountertopStream} stream The stream. * @return {String} The resulting kafka topic. */ exports.generateTributaryMaps = generateTributaryMaps; const getStreamTopic = (dataType, stream) => (0, _kafka.sanitizeTopic)(`${dataType}::${stream.id}`); exports.getStreamTopic = getStreamTopic; const isSubsetOf = (arr1, arr2) => arr1.every(value => arr2.includes(value)); /** * Returns any streams with the same station whose mouth + source is the same and whose * tributaries are a direct subset (or equal set). * * @param {CountertopStream[]} currentStreams The base set of streams. * @param {CountertopStream[]} nextStreams The new streams to use to determine pruning. * @return {CountertopStream[]} The pruned subset of the currentStreams */ const identifyObsoleteStreams = (currentStreams, nextStreams) => currentStreams.filter(currentStream => nextStreams.some(nextStream => currentStream.mouth.id === nextStream.mouth.id && currentStream.source.id === nextStream.source.id && isSubsetOf(currentStream.getTributaryArray(), nextStream.getTributaryArray()))); exports.identifyObsoleteStreams = identifyObsoleteStreams; const pruneStreams = (currentStreams, removedStreams) => removedStreams.reduce((remainingStreams, removedStream) => filterStreamsContainingStream(remainingStreams, removedStream), currentStreams); exports.pruneStreams = pruneStreams;