@zendesk/zcli-themes
Version:
zcli theme commands live here
110 lines (109 loc) • 5.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const path = require("path");
const fs = require("fs");
const express = require("express");
const http = require("http");
const https = require("https");
const WebSocket = require("ws");
const morgan = require("morgan");
const chalk = require("chalk");
const cors = require("cors");
const chokidar = require("chokidar");
const preview_1 = require("../../lib/preview");
const getManifest_1 = require("../../lib/getManifest");
const getVariables_1 = require("../../lib/getVariables");
const getAssets_1 = require("../../lib/getAssets");
const zass_1 = require("../../lib/zass");
const logMiddleware = morgan((tokens, req, res) => `${chalk.green(tokens.method(req, res))} ${tokens.url(req, res)} ${chalk.bold(tokens.status(req, res))}`);
class Preview extends core_1.Command {
async run() {
const { flags, argv: [themeDirectory] } = await this.parse(Preview);
const themePath = path.resolve(themeDirectory);
const { logs: tailLogs, bind: host, port, 'https-cert': httpsCert, 'https-key': httpsKey } = flags;
let httpsServerOptions = null;
if (httpsCert && httpsKey) {
httpsServerOptions = {
key: fs.readFileSync(httpsKey),
cert: fs.readFileSync(httpsCert)
};
}
const baseUrl = await (0, preview_1.default)(themePath, flags);
const app = express();
const server = httpsServerOptions === null ? http.createServer(app) : https.createServer(httpsServerOptions, app);
const wss = new WebSocket.Server({ server, path: '/livereload' });
app.use(cors());
tailLogs && app.use(logMiddleware);
app.use('/guide/assets', express.static(`${themePath}/assets`));
app.use('/guide/settings', express.static(`${themePath}/settings`));
app.get('/guide/script.js', (req, res) => {
const script = path.resolve(`${themePath}/script.js`);
const source = fs.readFileSync(script, 'utf8');
res.header('Content-Type', 'text/javascript');
res.send(source);
});
app.get('/guide/style.css', (req, res) => {
const style = path.resolve(`${themePath}/style.css`);
const source = fs.readFileSync(style, 'utf8');
const manifest = (0, getManifest_1.default)(themePath);
const variables = (0, getVariables_1.default)(themePath, manifest.settings, flags);
const assets = (0, getAssets_1.default)(themePath, flags);
const compiled = (0, zass_1.default)(source, variables, assets);
res.header('Content-Type', 'text/css');
res.send(compiled);
});
server.listen(port, host, async () => {
this.log(chalk.bold.green('Ready', chalk.blueBright(`${baseUrl}/hc/admin/local_preview/start`, '🚀')));
this.log(`You can exit preview mode in the UI or by visiting ${baseUrl}/hc/admin/local_preview/stop`);
tailLogs && this.log(chalk.bold('Tailing logs'));
});
const monitoredPaths = [
`${themePath}/assets`,
`${themePath}/settings`,
`${themePath}/templates`,
`${themePath}/manifest.json`,
`${themePath}/script.js`,
`${themePath}/style.css`
];
const watcher = chokidar.watch(monitoredPaths).on('change', async (path) => {
this.log(chalk.bold('Change'), path);
try {
await (0, preview_1.default)(themePath, flags);
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send('reload');
}
});
}
catch (e) {
this.error(e, { exit: false });
}
});
return {
close: () => {
// Stop watching file changes before terminating the server
watcher.close();
server.close();
wss.close();
}
};
}
}
exports.default = Preview;
Preview.description = 'preview a theme in development mode';
Preview.flags = {
bind: core_1.Flags.string({ default: 'localhost', description: 'Bind theme server to a specific host' }),
port: core_1.Flags.integer({ default: 4567, description: 'Port for the http server to use' }),
logs: core_1.Flags.boolean({ default: false, description: 'Tail logs' }),
livereload: core_1.Flags.boolean({ default: true, description: 'Enable or disable live-reloading the preview when a change is made', allowNo: true }),
'https-cert': core_1.Flags.file({ description: 'Certificate used to start the server in HTTPS mode' }),
'https-key': core_1.Flags.file({ description: 'Key used to start the server in HTTPS mode' })
};
Preview.args = [
{ name: 'themeDirectory', required: true, default: '.' }
];
Preview.examples = [
'$ zcli themes:preview ./copenhagen_theme'
];
Preview.strict = false;