UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

257 lines (223 loc) • 7.17 kB
import * as R from "ramda"; import { toCamelCase, toPascalCase } from "../stringUtils"; import { getNavigationType } from "../navigationUtils"; import { deprecationMessage } from "../appUtils"; import { pluginUtilsLogger } from "./logger"; import { platformSelect } from "../reactUtils"; type PluginModule = any; type Plugin = { module: PluginModule; type: string; name: string; identifier: string; configuration: any; }; /** * returns the component module for a specific type * Will look in components first, then in plugins */ export function getComponentModule({ componentType, components, plugins, }: { componentType: string; components: ComponentsMap; plugins: Plugin[] | QuickBrickPlugin[]; }) { const component = R.compose( R.prop(R.__, components), toPascalCase )(componentType); if (component) { return component; } return R.compose( R.prop("module"), R.defaultTo({}), R.find(R.propEq("identifier", componentType)) )(plugins); } /** * returns the component if it exists, returns undefined otherwise. also decorates * the component with the decorators if provided. */ export function findComponentByType({ componentType, components, decorators = R.identity, plugins = [], }) { const applyDecorators = Array.isArray(decorators) ? R.compose(...R.reverse(decorators)) : decorators; const component = getComponentModule({ componentType, components, plugins }); return R.unless(R.isNil, applyDecorators)(component); } /** * Returns the plugin for a given identifier, if found * @param identifier of the plugin to look for * @param plugins map of the available plugins * @param doNotWarn if set to true, will not log a warning if plugin is not found * @return whole plugin if found, undefined otherwise */ export function findPluginByIdentifier( identifier: string, plugins: (QuickBrickPlugin | ZappPlugin | Plugin)[], doNotWarn: boolean = false ): (QuickBrickPlugin | ZappPlugin | Plugin) | undefined { if (!identifier) { return undefined; } const plugin = R.compose( R.find(R.propEq("identifier", identifier)), R.values )(plugins); if (!plugin && identifier !== "river" && identifier !== "hooks") { if (!doNotWarn) { pluginUtilsLogger.warning({ message: `Could not find plugin for identifier ${identifier}`, data: { identifier }, }); } } return plugin; } const pluginTypeForItemTypeMap = { playable: "player", }; /** * return the type of plugin required for a type of item * when names don't match (see map above) * @param itemType requested * @returns matching result in the map above. returns the input otherwise */ function pluginTypeForItemTypeMapper(itemType) { return R.when( R.has(R.__, pluginTypeForItemTypeMap), R.prop(R.__, pluginTypeForItemTypeMap) )(itemType); } /** * returns the plugin module for a given type, if found * @param type of the plugin to look for * @param plugins map of the available plugins * @param returnFullObject if needed to return full instance of plugin (optional) * @return plugin module or whole plugin found, if any, undefined otherwise */ export function findPluginByType( type: string, plugins: (QuickBrickPlugin | Plugin)[], optionsOrReturnFullObject?: | { returnFullObject?: boolean; skipWarning?: boolean } | boolean ): PluginModule | (QuickBrickPlugin | Plugin) { let returnFullObject; let skipWarning = false; if (typeof optionsOrReturnFullObject === "boolean") { returnFullObject = optionsOrReturnFullObject; } else if (typeof optionsOrReturnFullObject === "object") { if (optionsOrReturnFullObject.skipWarning) { skipWarning = optionsOrReturnFullObject.skipWarning; } if (optionsOrReturnFullObject?.returnFullObject) { returnFullObject = optionsOrReturnFullObject.returnFullObject; } } const plugin = R.compose( R.find(R.propEq("type", pluginTypeForItemTypeMapper(type))), R.values )(plugins) || {}; const { module: pluginModule, configuration } = plugin; if (returnFullObject) { return plugin; } if (!pluginModule) { if (type !== "river" && type !== "hooks" && !skipWarning) { pluginUtilsLogger.warning({ message: `Could not find a module for type ${type}`, data: { type }, }); } return undefined; // eslint-disable-line no-undefined } pluginModule.__plugin_configuration = configuration; return pluginModule; } type Component = any; type ComponentsMap = { [key: string]: Component }; /** * returns a navigation plugin based on its type. if not found, returns undefined * @deprecated will be removed in next major version. Use NavigationUtils.resolveNavigationPlugin instead * @param options to provide to the function * @param options.category of navigation plugin to look for - can be either nav_bar or menu * @param options.navigations navigations data to look for plugin type * @param options.plugins map of available plugins * @param options.defaultNavigationComponents map of default components to use (optional) * @return plugin module found, if any */ export function getNavigationPlugin({ category, navigations, plugins, defaultNavigationComponents = {}, }: { category: "nav_bar" | "menu"; navigations: any[]; plugins: Plugin[]; defaultNavigationComponents: ComponentsMap; }): any { deprecationMessage( "@applicaster/zapp-react-native-utils/PluginUtils.getNavigationPlugin", "@applicaster/zapp-react-native-utils/NavigationUtils.resolveNavigationPlugin" ); return ( findPluginByType(getNavigationType(category, navigations), plugins) || defaultNavigationComponents[toPascalCase(category)] ); } /** * retrieves a Screen Plugin from the plugins array * curried function `findScreenPlugin(type)(plugins)` * @param type type of the plugin to look for. * will be camelCased, and matched to the name property in the plugins * @param plugins array of plugins to look into. * @param plugins[].module React component for the plugin * @param plugins[].name name of the plugin * @param plugins[].type type of the plugin * @return the plugin's module property (React component) */ export function findScreenPlugin(type) { return function (plugins) { return R.compose( R.prop("module"), R.find(R.propEq("name", toCamelCase(type))) )(plugins); }; } /** * * @param manifestConfig - manifest.config of your plugin * @param version - package.json of your plugin */ export function generateManifest({ manifestConfig, version }) { const platform = platformSelect({ ios: "ios_for_quickbrick", android: "android_for_quickbrick", android_tv: "android_tv_for_quickbrick", amazon: "amazon_fire_tv_for_quickbrick", samsung_tv: "samsung_tv", lg_tv: "lg_tv", tvos: "tvos_for_quickbrick", web: "samsung_tv", }); return manifestConfig({ platform, version }); } const getPluginType = R.pathOr("unknown_plugin_type", [ "state", "screen", "plugin_type", ]); export const isPlayerPlugin = (routeState): boolean => getPluginType(routeState) === "player";