-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cli commands #490
Cli commands #490
Changes from 10 commits
89fb45b
dcc5ef7
010f42f
5f3a3ba
2f35d17
f5c164c
2952ae7
b7d02ce
996c589
04ed22b
b436d03
1183e10
4e1b941
534b63e
06e7609
7cc1420
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Can't use `instanceof` with babel-ified subclasses of builtins. | ||
// | ||
// https://phabricator.babeljs.io/T3083 | ||
// | ||
// Gotta do this the old-fashioned way. :p | ||
// | ||
export default function ConfigurationError(message) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might want to consider using VError for our custom error classes |
||
this.name = 'ConfigurationError'; | ||
this.message = message; | ||
this.stack = (new Error()).stack; | ||
} | ||
ConfigurationError.prototype = Object.create(Error.prototype); | ||
ConfigurationError.prototype.constructor = ConfigurationError; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
require("babel-core/register"); | ||
|
||
const {start, parseCliArgs} = require("."); | ||
const {run, parseCliArgs} = require("."); | ||
|
||
start(parseCliArgs()); | ||
run(parseCliArgs()); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import _ from "lodash"; | ||
import fs from "fs"; | ||
import {join} from "path"; | ||
import chalk from "chalk"; | ||
import mkdirp from "mkdirp"; | ||
import fileExists from "../fileExists"; | ||
import ConfigurationError from "../ConfigurationError"; | ||
|
||
const PAGE_SOURCE = _.template(` | ||
import React from "react"; | ||
|
||
export default class <%= className %> { | ||
handleRoute(next) { | ||
// Kick off data requests here. | ||
return next(); | ||
} | ||
|
||
getElements() { | ||
return <div>This is <%= className %>.</div> | ||
} | ||
} | ||
`); | ||
|
||
export default function addPage(options){ | ||
const {routesFile, routesPath, routes} = options; | ||
|
||
const path = options._[3]; | ||
const className = options._[4]; | ||
|
||
if (!path || !className) { | ||
throw new ConfigurationError("Usage: react-server add-page <urlPath> <ClassName>"); | ||
} | ||
|
||
const page = join("pages", className + ".js"); | ||
|
||
if (fileExists(page)) { | ||
throw new ConfigurationError(`Found a pre-existing ${page}. Aborting.`); | ||
} | ||
|
||
mkdirp("pages"); | ||
|
||
console.log(chalk.yellow("Generating " + page)); | ||
|
||
fs.writeFileSync(page, PAGE_SOURCE({className})); | ||
|
||
routes.routes[className] = { path, page }; | ||
|
||
console.log(chalk.yellow("Updating " + routesFile)); | ||
|
||
fs.writeFileSync(routesPath, JSON.stringify(routes, null, " ") + "\n"); | ||
|
||
console.log(chalk.green("All set!")); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import compileClient from "../compileClient" | ||
import handleCompilationErrors from "../handleCompilationErrors"; | ||
import setupLogging from "../setupLogging"; | ||
import logProductionWarnings from "../logProductionWarnings"; | ||
|
||
const logger = require("react-server").logging.getLogger(__LOGGER__); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought we were trying to set the pattern of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch. |
||
|
||
export default function compile(options){ | ||
setupLogging(options); | ||
logProductionWarnings(options); | ||
|
||
const {compiler} = compileClient(options); | ||
|
||
logger.notice("Starting compilation of client JavaScript..."); | ||
compiler.run((err, stats) => { | ||
const error = handleCompilationErrors(err, stats); | ||
if (!error) { | ||
logger.notice("Successfully compiled client JavaScript."); | ||
} else { | ||
logger.error(error); | ||
} | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import _ from "lodash"; | ||
import fs from "fs"; | ||
import {spawnSync} from "child_process"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer spawn, personally -- we're using babel afaict, so you can use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no concurrency among subprocesses here. Easier flow of control this way. |
||
import chalk from "chalk"; | ||
import fileExists from "../fileExists"; | ||
import ConfigurationError from "../ConfigurationError"; | ||
|
||
const DEPENDENCIES = [ | ||
"react-server", | ||
"babel-preset-react-server", | ||
|
||
// TODO: Modernize our peer deps and remove versions here. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes please |
||
"superagent@1.2.0", | ||
"react@~0.14.2", | ||
"react-dom@~0.14.2", | ||
] | ||
|
||
const DEV_DEPENDENCIES = [ | ||
|
||
// TODO: These, too. | ||
"webpack-dev-server@~1.13.0", | ||
"webpack@^1.13.1", | ||
] | ||
|
||
const CONFIG = { | ||
"routes.json": { | ||
middleware: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we init with a single page/route? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe? My thought was if you want a page you can generate it with |
||
routes: {}, | ||
}, | ||
".reactserverrc": { | ||
routesFile: "routes.json", | ||
port: 3000, | ||
env: { | ||
production: { | ||
port: 80, | ||
}, | ||
}, | ||
}, | ||
".babelrc": { | ||
presets: ["react-server"], | ||
}, | ||
} | ||
|
||
export default function init(){ | ||
|
||
if (!fileExists("package.json")) { | ||
throw new ConfigurationError("Missing package.json. Please run `npm init` first."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... yeah, I like it. |
||
} | ||
|
||
Object.keys(CONFIG).forEach(fn => { | ||
if (fileExists(fn)) { | ||
throw new ConfigurationError(`Found a pre-existing ${fn}. Aborting.`); | ||
} | ||
}); | ||
|
||
console.log(chalk.yellow("Installing dependencies")); | ||
|
||
spawnSync("npm", ["install", "--save", ...DEPENDENCIES], {stdio: "inherit"}); | ||
|
||
console.log(chalk.yellow("Installing devDependencies")); | ||
|
||
spawnSync("npm", ["install", "--save-dev", ...DEV_DEPENDENCIES], {stdio: "inherit"}); | ||
|
||
_.forEach(CONFIG, (config, fn) => { | ||
console.log(chalk.yellow("Generating " + fn)); | ||
|
||
fs.writeFileSync(fn, JSON.stringify(config, null, " ") + "\n"); | ||
}); | ||
|
||
console.log(chalk.green("All set!")); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't 3001 conflict with react-server-integration-test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. I think
react-server-integration-test
uses a dummy static asset server.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, you're right. 😞