UNPKG

6.27 kBJavaScriptView Raw
1#!/usr/bin/env node
2'use strict';
3
4const meow = require('meow');
5const chalk = require('chalk');
6const path = require('path');
7const fs = require('fs');
8const batfishLog = require('../dist/node/batfish-log');
9const start = require('../dist/node/start');
10const build = require('../dist/node/build');
11const serveStatic = require('../dist/node/serve-static');
12const writeBabelrc = require('../dist/node/write-babelrc');
13const getLoggableErrorMessage = require('../dist/node/get-loggable-error-message');
14const renderPrettyErrorStack = require('../dist/node/render-pretty-error-stack');
15const constants = require('../dist/node/constants');
16
17const commands = {
18 start,
19 build,
20 'serve-static': serveStatic,
21 'write-babelrc': writeBabelrc
22};
23
24const description = `Build websites with batfish.`;
25const help = `
26${chalk.bold('Usage')}
27 batfish <command> [options]
28
29 You must provide a batfish configuration module, either with
30 batish.config.js in process.cwd() or with the --config option.
31
32${chalk.bold('Commands')}
33 start Start a development server.
34 build Build the static site.
35 serve-static Serve the static site.
36 write-babelrc Write a .babelrc file that other processes,
37 like your test runner, can use.
38
39${chalk.bold('Shared options')}
40 -c, --config Path to your configuration module.
41 Default: batfish.config.js
42 -V, --verbose Log extra stats.
43
44${chalk.bold(`${chalk.magenta('start')} options`)}
45 -p, --port Server port. Default: 8080.
46 -i, --include Build only the specified page(s). Value
47 is a glob relative to the root of your site.
48 --production Build as though for production.
49 --no-clear Do not clear the destination directory.
50 -b, --browsers A comma-separated browserslist string
51 specifying the browsers you want to support
52 during this dev build. Or "false" if you
53 want to support all your production browsers.
54
55${chalk.bold(`${chalk.magenta('build')} options`)}
56 -d, --debug Build for debugging, not for production.
57 --no-clear Do not clear the destination directory.
58
59${chalk.bold(`${chalk.magenta('serve-static')} options`)}
60 -p, --port Server port. Default: 8080.
61
62${chalk.bold(`${chalk.magenta('write-babelrc')} options`)}
63 --target "node" or "browser". Default: "node".
64 --dir Directory where .babelrc should be written.
65 Default: same directory as Batfish config.
66
67${chalk.bold('Examples')}
68 No options are required for any command.
69 ${chalk.cyan('batfish start')}
70 ${chalk.cyan('batfish build')}
71 ${chalk.cyan('batfish serve-static')}
72 ${chalk.cyan('batfish write-babelrc')}
73 Build with your Batfish config in a special place.
74 ${chalk.cyan('batfish build -c conf/bf.js')}
75 Start with an alternate port.
76 ${chalk.cyan('batfish start -p 9966')}
77 Start but only build the /about pages.
78 ${chalk.cyan('batfish start -i about/**')}
79 Start but only build the /about/history page.
80 ${chalk.cyan('batfish start --include about/history')}
81 Start and build only for Chrome 60+.
82 ${chalk.cyan('batfish start --browsers "Chrome >= 60"')}
83`;
84
85const cli = meow({
86 description,
87 help,
88 flags: {
89 config: {
90 type: 'string',
91 alias: 'c'
92 },
93 verbose: {
94 type: 'boolean',
95 alias: 'V'
96 },
97 port: {
98 type: 'number',
99 alias: 'p'
100 },
101 debug: {
102 type: 'boolean',
103 alias: 'd'
104 },
105 target: {
106 type: 'string'
107 },
108 dir: {
109 type: 'string'
110 },
111 include: {
112 type: 'string',
113 alias: 'i'
114 },
115 browsers: {
116 type: 'string',
117 alias: 'b'
118 }
119 }
120});
121
122const logCliError = (message) => {
123 batfishLog.error(`${chalk.red.bold('CLI error:')} ${message}`);
124};
125
126const command = cli.input[0];
127if (command === undefined || commands[command] === undefined) {
128 logCliError('You must specify a valid command.');
129 cli.showHelp();
130}
131
132const isDefaultConfigPath = cli.flags.config === undefined;
133let configPath;
134if (cli.flags.config) {
135 configPath = path.isAbsolute(cli.flags.config)
136 ? cli.flags.config
137 : path.join(process.cwd(), cli.flags.config);
138} else {
139 configPath = path.join(process.cwd(), 'batfish.config.js');
140}
141
142let config = {};
143if (configPath) {
144 try {
145 if (fs.existsSync(configPath)) {
146 const configModule = require(configPath);
147 if (typeof configModule !== 'function') {
148 logCliError(
149 'Your configuration module must export a function that returns an object.'
150 );
151 process.exit(2);
152 }
153 config = configModule();
154 }
155 } catch (error) {
156 if (!isDefaultConfigPath) {
157 logCliError(
158 `Failed to load configuration module from ${chalk.underline(
159 configPath
160 )}`
161 );
162 }
163 throw error;
164 }
165}
166
167if (cli.flags.production) {
168 config.production = cli.flags.production;
169} else if (command === 'build') {
170 config.production = true;
171}
172if (cli.flags.debug) {
173 config.production = !cli.flags.debug;
174}
175if (cli.flags.port) {
176 config.port = cli.flags.port;
177}
178if (cli.flags.verbose) {
179 config.verbose = cli.flags.verbose;
180}
181if (command === 'start' && cli.flags.include) {
182 config.includePages = [].concat(cli.flags.include);
183}
184if (cli.flags.clear === false) {
185 config.clearOutputDirectory = false;
186}
187if (command === 'start' && cli.flags.browsers) {
188 config.devBrowserslist =
189 cli.flags.browsers === 'false' ? false : cli.flags.browsers;
190}
191
192const projectDirectory = path.dirname(configPath);
193
194(() => {
195 if (command === 'write-babelrc') {
196 writeBabelrc(config, {
197 projectDirectory,
198 outputDirectory: cli.flags.dir,
199 target: cli.flags.target
200 });
201 return;
202 }
203
204 const executeCommand = commands[command];
205 const emitter = executeCommand(config, projectDirectory);
206 emitter.on(constants.EVENT_NOTIFICATION, (message) => {
207 batfishLog.log(message);
208 });
209 emitter.on(constants.EVENT_ERROR, (error) => {
210 const niceMessage = getLoggableErrorMessage(error);
211 if (niceMessage) {
212 batfishLog.error(niceMessage);
213 } else {
214 batfishLog.error(renderPrettyErrorStack(error));
215 }
216 if (command !== 'start') {
217 process.exit(1);
218 }
219 });
220})();