UNPKG

@viewdo/dxp-story-cli

Version:
269 lines (223 loc) 8.05 kB
// Deps const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const express = require('express'); const app = express(); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const path = require('path'); const jsonPlugin = require("../config/json-plugin"); const iVXStoryPlayer = require('ivx-story-player'); const exphbs = require('express-handlebars'); const opn = require('opn'); // Change when we move this over to the CLI const defaultEpisodeKey = process.env.DEFAULT_EPISODE_KEY|| "index"; // Routes const homePage = require("./routes/home"); // Story Player Preview Configs const tools = "https://ivx-tools.develop.dotedu.com"; const spPort = 3060; const appConfig = { api: { xapi: "http://localhost:3090" }, urls: { tools, storyPlayer: `http://localhost:${spPort}` }, storyPlayerUrls: { experienceHostUrl: `${tools}/ivx-experience/v1/ivx-experience.js` }, environment: "dev", preview: true, platformXapiUrl: `https://ivx-xapi.develop.dotedu.com/v1`, port: spPort } // Tests to see if the current config is for the index.js file const _getStoryInfoFromJsConfig = (iVXConfig, config) => { const {stories = {}, source = "./src"} = iVXConfig; const storyKeys = Object.keys(stories); const {entry} = config; let storyInfo; storyKeys.forEach(storyKey=>{ const sourcePath = `${source}/${storyKey}`; const defaultEpisodeJs = `${sourcePath}/${defaultEpisodeKey}.js`; if(defaultEpisodeJs === entry) storyInfo = {storyKey}; const {episodes = {}} = stories[storyKey]; const episodeKeys = Object.keys(episodes); episodeKeys.forEach(episodeKey=>{ const episodeJs = `${sourcePath}/${episodeKey}.js`; if(entry === episodeJs) storyInfo = {storyKey, episodeKey}; }); }); return storyInfo; }; // Tests to see if the current config is for the index.json.js file const _getStoryInfoFromJsonConfig = (iVXConfig, config) => { const {stories = {}, source = "./src"} = iVXConfig; const storyKeys = Object.keys(stories); const {entry} = config; let storyInfo; storyKeys.forEach(storyKey=>{ const sourcePath = `${source}/${storyKey}`; const defaultEpisodeJs = `${sourcePath}/${defaultEpisodeKey}.json.js`; if(defaultEpisodeJs === entry) storyInfo = {storyKey}; const {episodes = {}} = stories[storyKey]; const episodeKeys = Object.keys(episodes); episodeKeys.forEach(episodeKey=>{ const episodeJs = `${sourcePath}/${episodeKey}.json.js`; if(entry === episodeJs) storyInfo = {storyKey, episodeKey}; }); }); return storyInfo; }; // Updates the JS Config with settings to support the dev server const mapJsConfig = (config, storyInfo) => { const {storyKey, episodeKey} = storyInfo; let fileName = storyKey; if(episodeKey) fileName = `${fileName}-${episodeKey}`; const xapiCssFileExtractor = new ExtractTextPlugin(`${fileName}.css`); const clonedConfig = Object.assign({}, config); const { module: configModule = {}, plugins = [] } = clonedConfig; const { rules = [] } = configModule; const cleanedRules = rules.filter(rule => { const { test } = rule; const currentTest = new RegExp(test); const lessTest = new RegExp(/\.less$/); return currentTest.toString() !== lessTest.toString(); }); const updateModules = { rules: [...cleanedRules, { test: /.html-templates/, use: { loader: 'file-loader', options: { name: (file) => { return `${storyKey}/template/[name].html`; }, context: '' } } }, { test: /\.less$/, loader: xapiCssFileExtractor.extract({ fallback: 'style-loader', use: ['css-loader', { loader: 'less-loader', options: { relativeUrls: true } }] }) }, { /* For Windows... */ test: /.\\story\-config.json/, use: [{ loader: 'file-loader', options: { name: (file) => { return `${storyKey}\\index.html`; }, context: '' } },{ loader: path.resolve(__dirname, 'loaders/story-config.js') }] },{ /* For *NIX... */ test: /.\/story\-config.json/, use: [{ loader: 'file-loader', options: { name: (file) => { return `${storyKey}/index.html`; }, context: '' } },{ loader: path.resolve(__dirname, 'loaders/story-config.js') }] }] } const mappedConfig = Object.assign(clonedConfig, { module: updateModules, plugins: [...plugins, xapiCssFileExtractor ], output: { filename: `${fileName}.js`, path: path.resolve('/story/story') // THIS WORKS FOR SOME REASON } }); return mappedConfig; } // Updates the JSON config to use with the dev server const mapJsonConfig = (config, storyInfo) => { const {storyKey, episodeKey} = storyInfo; let fileName = storyKey; if(episodeKey) fileName = `${fileName}-${episodeKey}`; const clonedConfig = Object.assign({}, config); return Object.assign(clonedConfig, { output: { filename: `_json-evaluator.js`, path: path.resolve(`/story`) }, plugins: [new jsonPlugin({ buildFile: `${fileName}.json`, buildPath: `story`, serve: true })] }); } // Depending on the config, this will add the changes to run the dev // middleware server. const _updateConfigs = (configs, iVXConfig) => { const { stories, source = "./src" } = iVXConfig; const storyKeys = Object.keys(stories); return configs.map(config => { const matchingJsConfig = _getStoryInfoFromJsConfig(iVXConfig, config); const matchingJsonConfig = _getStoryInfoFromJsonConfig(iVXConfig, config); if (matchingJsConfig) { return mapJsConfig(config, matchingJsConfig); } if (matchingJsonConfig) { return mapJsonConfig(config, matchingJsonConfig) } return config }); } /** * Using the configs built by the main service for webpack, this will * use the webpackDevMiddleware for express to create a local server as * an instance of the xapi endpoint to support the preview with the ivx-story-player module. * * Returns a mini-api to open the window to preview and be able to reload the * browser when an update to the src folder occurs. */ module.exports = (configs, iVXConfig) => { const updatedConfigs = _updateConfigs(configs, iVXConfig); app.set('views', './_cli/build-scripts/services/webpack/server/views/layouts'); app.engine('handlebars', exphbs({ defaultLayout: 'main', layoutsDir: './_cli/build-scripts/services/webpack/server/views/layouts' })); app.set('view engine', 'handlebars'); app.use(webpackDevMiddleware(webpack(updatedConfigs), { stats: { chunks: true, colors: true } })); //Routes homePage(app, iVXConfig, appConfig); const spServer = iVXStoryPlayer(appConfig); app.listen(3090, () => console.log(`The preview selector page can be found at http://localhost:${3090}` )); return Object.assign({}, spServer, { openWindow: () => { opn(appConfig.api.xapi); } } ); }