Browse Source

feat: Use oclif cli for server; clean up webpack config

update-deps
Alex Mikhalev 6 years ago
parent
commit
46f4b9d14a
  1. 9
      bin/sprinklers3
  2. 77
      client/env.js
  3. 108
      client/webpack.config.js
  4. 126
      common/browserLogger.ts
  5. 120
      common/logger.ts
  6. 28
      package.json
  7. 6
      server/Database.ts
  8. 28
      server/bin/server.ts
  9. 11
      server/commands/manage.ts
  10. 17
      server/commands/pretty.ts
  11. 33
      server/commands/serve.ts
  12. 18
      server/state.ts
  13. 179
      yarn.lock

9
bin/sprinklers3

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
#!/usr/bin/env node
const { run } = require("@oclif/command");
const flush = require("@oclif/command/flush");
const handleError = require("@oclif/errors/handle");
run()
.then(flush)
.catch(handleError);

77
client/env.js

@ -1,58 +1,45 @@ @@ -1,58 +1,45 @@
const fs = require("fs");
const path = require("path");
const dotenv = require("dotenv");
const paths = require("../paths")
const NODE_ENV = process.env.NODE_ENV;
if (!NODE_ENV) {
throw new Error(
"The NODE_ENV environment variable is required but was not specified.",
);
}
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
const dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`,
// Don"t include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== "test" && `${paths.dotenv}.local`,
paths.dotenv,
].filter(Boolean);
const validEnvs = ["production", "development"];
// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set.
// https://github.com/motdotla/dotenv
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
require("dotenv").config({
path: dotenvFile,
});
exports.loadEnv = function loadEnv(env) {
if (validEnvs.indexOf(env) === -1) {
throw new Error("Must specify webpack --env as one of: " + validEnvs.join(','));
}
});
// We support resolving modules according to `NODE_PATH`.
// This lets you use absolute paths in imports inside large monorepos:
// https://github.com/facebookincubator/create-react-app/issues/253.
// It works similar to `NODE_PATH` in Node itself:
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
// We also resolve them to make sure all tools using them work consistently.
const appDirectory = fs.realpathSync(process.cwd());
process.env.NODE_PATH = (process.env.NODE_PATH || "")
.split(path.delimiter)
.filter(folder => folder && !path.isAbsolute(folder))
.map(folder => path.resolve(appDirectory, folder))
.join(path.delimiter);
const dotenvFiles = [
`${paths.dotenv}.${env}.local`,
`${paths.dotenv}.${env}`,
// Don"t include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
env !== "test" && `${paths.dotenv}.local`,
paths.dotenv,
].filter(Boolean);
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
dotenv.config({
path: dotenvFile,
});
}
});
delete require.cache[require.resolve("../paths")]; // so new env applies
return {
isProd: env === "production",
isDev: env === "development"
};
}
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
const REACT_APP = /^REACT_APP_/i;
exports.getClientEnvironment = function getClientEnvironment(publicUrl) {
exports.getClientEnvironment = function getClientEnvironment(env, publicUrl) {
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce(
@ -62,7 +49,7 @@ exports.getClientEnvironment = function getClientEnvironment(publicUrl) { @@ -62,7 +49,7 @@ exports.getClientEnvironment = function getClientEnvironment(publicUrl) {
}, {
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || "development",
NODE_ENV: process.env.NODE_ENV || env,
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + "/img/logo.png"} />.
// This should only be used as an escape hatch. Normally you would put

108
client/webpack.config.js

@ -11,53 +11,58 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") @@ -11,53 +11,58 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const { getClientEnvironment } = require("./env");
const paths = require("../paths");
const { loadEnv, getClientEnvironment } = require("./env");
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
const publicPath = paths.publicPath;
// `publicUrl` is just like `publicPath`, but we will provide it to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = paths.publicUrl.slice(0, -1);
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
// Get environment variables to inject into our app.
const environ = getClientEnvironment(publicUrl);
function getConfig(env) {
const { isProd, isDev } = loadEnv(env);
const postCssConfig = {
loader: require.resolve("postcss-loader"),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: "postcss",
plugins: () => [
require("postcss-flexbugs-fixes"),
require("postcss-preset-env")({
stage: 0
})
]
}
};
const paths = require("../paths");
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
const publicPath = paths.publicPath;
// `publicUrl` is just like `publicPath`, but we will provide it to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = paths.publicUrl.slice(0, -1);
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
const shouldExtractCss = process.env.EXTRACT_CSS
? process.env.EXTRACT_CSS === "true"
: isProd;
// Get environment variables to inject into our app.
const environ = getClientEnvironment(env, publicUrl);
const postCssConfig = {
loader: require.resolve("postcss-loader"),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: "postcss",
plugins: () => [
require("postcss-flexbugs-fixes"),
require("postcss-preset-env")({
stage: 0
})
]
}
};
const sassConfig = {
loader: require.resolve("sass-loader"),
options: {}
};
const sassConfig = {
loader: require.resolve("sass-loader"),
options: {}
};
const rules = env => {
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
const styleLoader =
env === "prod"
? {
loader: MiniCssExtractPlugin.loader
}
: require.resolve("style-loader");
const styleLoader = shouldExtractCss
? {
loader: MiniCssExtractPlugin.loader
}
: require.resolve("style-loader");
const cssRule = {
test: /\.css$/,
use: [
@ -85,7 +90,8 @@ const rules = env => { @@ -85,7 +90,8 @@ const rules = env => {
sassConfig
]
};
return [
const rules = [
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. when no loader matches it will fall
@ -98,7 +104,7 @@ const rules = env => { @@ -98,7 +104,7 @@ const rules = env => {
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve("url-loader"),
options: {
limit: env === "prod" ? 10000 : 0,
limit: env === "production" ? 10000 : 0,
name: "static/media/[name].[hash:8].[ext]"
}
},
@ -144,19 +150,6 @@ const rules = env => { @@ -144,19 +150,6 @@ const rules = env => {
]
}
];
};
const getConfig = (module.exports = env => {
const isProd = env === "prod";
const isDev = env === "dev";
// Assert this just to be safe.
// Development builds of React are slow and not intended for production.
if (
isProd &&
environ.stringified["process.env"].NODE_ENV !== '"production"'
) {
throw new Error("Production builds must have NODE_ENV=production.");
}
const plugins = [
new HtmlWebpackPlugin({
@ -191,7 +184,6 @@ const getConfig = (module.exports = env => { @@ -191,7 +184,6 @@ const getConfig = (module.exports = env => {
sourceMap: shouldUseSourceMap
}),
isDev && new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new ForkTsCheckerWebpackPlugin({
checkSyntacticErrors: true,
tsconfig: paths.clientTsConfig,
@ -248,9 +240,7 @@ const getConfig = (module.exports = env => { @@ -248,9 +240,7 @@ const getConfig = (module.exports = env => {
"@common": paths.commonDir
}
},
module: {
rules: rules(env)
},
module: { rules },
plugins: plugins,
optimization: {
namedModules: isProd
@ -268,4 +258,6 @@ const getConfig = (module.exports = env => { @@ -268,4 +258,6 @@ const getConfig = (module.exports = env => {
]
}
};
});
}
module.exports = getConfig;

126
common/browserLogger.ts

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
import * as pino from "pino";
// tslint:disable:no-console
type Level = "default" | "60" | "50" | "40" | "30" | "20" | "10";
const levels: { [level in Level]: string } = {
default: "USERLVL",
60: "FATAL",
50: "ERROR",
40: "WARN",
30: "INFO",
20: "DEBUG",
10: "TRACE"
};
const levelColors: { [level in Level]: string } = {
default: "text-decoration: underline; color: #000000;",
60: "text-decoration: underline; background-color: #FF0000;",
50: "text-decoration: underline; color: #FF0000;",
40: "text-decoration: underline; color: #FFFF00;",
30: "text-decoration: underline; color: #00FF00;",
20: "text-decoration: underline; color: #0000FF;",
10: "text-decoration: underline; color: #AAAAAA;"
};
interface ColoredString {
str: string;
args: any[];
}
function makeColored(str: string = ""): ColoredString {
return { str, args: [] };
}
function concatColored(...coloredStrings: ColoredString[]): ColoredString {
return coloredStrings.reduce(
(prev, cur) => ({
str: prev.str + cur.str,
args: prev.args.concat(cur.args)
}),
makeColored()
);
}
const standardKeys = [
"pid",
"hostname",
"name",
"level",
"time",
"v",
"source",
"msg"
];
export function write(value: any) {
let line = concatColored(
// makeColored(formatTime(value, " ")),
formatSource(value),
formatLevel(value),
makeColored(": ")
);
if (value.msg) {
line = concatColored(line, {
str: "%c" + value.msg,
args: ["color: #00FFFF"]
});
}
const args = [line.str]
.concat(line.args)
.concat([value.type === "Error" ? value.stack : filter(value)]);
let fn;
if (value.level >= 50) {
fn = console.error;
} else if (value.level >= 40) {
fn = console.warn;
} else {
fn = console.log;
}
fn.apply(null, args);
}
function filter(value: any) {
const keys = Object.keys(value);
const result: any = {};
for (const key of keys) {
if (standardKeys.indexOf(key) < 0) {
result[key] = value[key];
}
}
return result;
}
function formatSource(value: any): { str: string; args: any[] } {
if (value.source) {
return { str: "%c(" + value.source + ") ", args: ["color: #FF00FF"] };
} else {
return { str: "", args: [] };
}
}
function formatLevel(value: any): ColoredString {
const level = value.level as Level;
if (levelColors.hasOwnProperty(level)) {
return {
str: "%c" + levels[level] + "%c",
args: [levelColors[level], ""]
};
} else {
return {
str: levels.default,
args: [levelColors.default]
};
}
}
const browserLogger = {
serialize: true,
write,
};
export default browserLogger;

120
common/logger.ts

@ -1,126 +1,10 @@ @@ -1,126 +1,10 @@
import * as pino from "pino";
// tslint:disable:no-console
type Level = "default" | "60" | "50" | "40" | "30" | "20" | "10";
const levels: { [level in Level]: string } = {
default: "USERLVL",
60: "FATAL",
50: "ERROR",
40: "WARN",
30: "INFO",
20: "DEBUG",
10: "TRACE"
};
const levelColors: { [level in Level]: string } = {
default: "text-decoration: underline; color: #000000;",
60: "text-decoration: underline; background-color: #FF0000;",
50: "text-decoration: underline; color: #FF0000;",
40: "text-decoration: underline; color: #FFFF00;",
30: "text-decoration: underline; color: #00FF00;",
20: "text-decoration: underline; color: #0000FF;",
10: "text-decoration: underline; color: #AAAAAA;"
};
interface ColoredString {
str: string;
args: any[];
}
function makeColored(str: string = ""): ColoredString {
return { str, args: [] };
}
function concatColored(...coloredStrings: ColoredString[]): ColoredString {
return coloredStrings.reduce(
(prev, cur) => ({
str: prev.str + cur.str,
args: prev.args.concat(cur.args)
}),
makeColored()
);
}
const standardKeys = [
"pid",
"hostname",
"name",
"level",
"time",
"v",
"source",
"msg"
];
function write(value: any) {
let line = concatColored(
// makeColored(formatTime(value, " ")),
formatSource(value),
formatLevel(value),
makeColored(": ")
);
if (value.msg) {
line = concatColored(line, {
str: "%c" + value.msg,
args: ["color: #00FFFF"]
});
}
const args = [line.str]
.concat(line.args)
.concat([value.type === "Error" ? value.stack : filter(value)]);
let fn;
if (value.level >= 50) {
fn = console.error;
} else if (value.level >= 40) {
fn = console.warn;
} else {
fn = console.log;
}
fn.apply(null, args);
}
function filter(value: any) {
const keys = Object.keys(value);
const result: any = {};
for (const key of keys) {
if (standardKeys.indexOf(key) < 0) {
result[key] = value[key];
}
}
return result;
}
function formatSource(value: any): { str: string; args: any[] } {
if (value.source) {
return { str: "%c(" + value.source + ") ", args: ["color: #FF00FF"] };
} else {
return { str: "", args: [] };
}
}
function formatLevel(value: any): ColoredString {
const level = value.level as Level;
if (levelColors.hasOwnProperty(level)) {
return {
str: "%c" + levels[level] + "%c",
args: [levelColors[level], ""]
};
} else {
return {
str: levels.default,
args: [levelColors.default]
};
}
}
import browserLogger from "./browserLogger";
const logger: pino.Logger = pino({
serializers: pino.stdSerializers,
browser: { serialize: true, write },
browser: browserLogger,
level: "trace"
});

28
package.json

@ -1,21 +1,22 @@ @@ -1,21 +1,22 @@
{
"name": "sprinklers3",
"version": "1.0.0",
"version": "0.0.1",
"private": true,
"description": "A frontend for mqtt based IoT sprinklers systems",
"main": "dist/bin/server.js",
"description": "A SPA web app for mqtt based IoT sprinklers systems",
"bin": "./bin/sprinklers3",
"main": "./bin/sprinklers3",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"clean": "rm -rf ./dist ./build ./public",
"build:client": "NODE_ENV=production webpack --config ./client/webpack.config.js --env prod",
"build:client": "webpack --config ./client/webpack.config.js --env production",
"build:server": "tsc --build server",
"build": "run-p build:*",
"watch:client": "yarn build:client --watch",
"watch:server": "yarn build:server --watch",
"start:dev-server": "NODE_ENV=development webpack-dev-server --config ./client/webpack.config.js --env dev",
"start": "NODE_ENV=development node .",
"start:pretty": "yarn start | node dist/bin/prettyPrint.js",
"start:nodemon": "nodemon --delay 0.5 --exec \"env NODE_ENV=development node . | node dist/bin/prettyPrint.js\"",
"start:dev-server": "webpack-dev-server --config ./client/webpack.config.js --env development",
"start": "node . serve",
"start:pretty": "node . serve | node . prettyPrint",
"start:nodemon": "nodemon --delay 0.5 --exec \"node . serve | node . prettyPrint\"",
"start:watch": "run-p watch:server start:nodemon",
"start:dev": "run-p start:dev-server start:watch",
"lint:client": "tslint --project client --force --format verbose",
@ -23,6 +24,7 @@ @@ -23,6 +24,7 @@
"lint": "run-p lint:*"
},
"files": [
"paths.js",
"dist",
"public"
],
@ -36,11 +38,19 @@ @@ -36,11 +38,19 @@
"url": "https://github.com/amikhalev/sprinklers3/issues"
},
"homepage": "https://github.com/amikhalev/sprinklers3#readme",
"oclif": {
"title": "sprinklers3",
"commands": "./dist/commands"
},
"dependencies": {
"@oclif/command": "^1.5.0",
"@oclif/config": "^1.7.4",
"@oclif/plugin-help": "^2.1.1",
"@types/split2": "^2.1.6",
"bcrypt": "^3.0.0",
"body-parser": "^1.18.3",
"chalk": "^2.4.1",
"cli-ux": "^4.8.1",
"express": "^4.16.3",
"express-pino-logger": "^4.0.0",
"express-promise-router": "^3.0.3",
@ -128,7 +138,7 @@ @@ -128,7 +138,7 @@
"tslint-config-prettier": "^1.15.0",
"tslint-consistent-codestyle": "^1.13.3",
"tslint-react": "^3.6.0",
"typescript": "^3.0.3",
"typescript": "^3.1.0 || >=3.1.0-dev.20180901",
"uglify-es": "^3.3.9",
"uglifyjs-webpack-plugin": "^1.3.0",
"url-loader": "^1.1.1",

6
server/Database.ts

@ -38,12 +38,10 @@ export class Database { @@ -38,12 +38,10 @@ export class Database {
}
async createAll() {
if (process.env.INSERT_TEST_DATA) {
await this.insertData();
}
}
async insertData() {
async insertTestData() {
const NUM = 100;
const users: User[] = [];
for (let i = 0; i < NUM; i++) {

28
server/bin/server.ts

@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
import * as http from "http";
import * as WebSocket from "ws";
import { createApp, ServerState, WebSocketApi } from "../";
import log from "@common/logger";
const state = new ServerState();
const app = createApp(state);
const webSocketApi = new WebSocketApi(state);
const port = +(process.env.PORT || 8080);
const host = process.env.HOST || "0.0.0.0";
const server = new http.Server(app);
const webSocketServer = new WebSocket.Server({ server });
webSocketApi.listen(webSocketServer);
state
.start()
.then(() => {
server.listen(port, host, () => {
log.info(`listening at ${host}:${port}`);
});
})
.catch(err => {
log.error({ err }, "error starting server");
});

11
server/commands/manage.ts

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
import Command from "@oclif/command";
import { createApp, ServerState, WebSocketApi } from "../";
import log from "@common/logger";
export default class ManageCommand extends Command {
run(): Promise<any> {
throw new Error("Method not implemented.");
}
}

17
server/bin/prettyPrint.ts → server/commands/pretty.ts

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
import { Command } from "@oclif/command";
import chalk from "chalk";
import * as pump from "pump";
import * as split from "split2";
@ -132,22 +133,26 @@ function asColoredLevel(value: any) { @@ -132,22 +133,26 @@ function asColoredLevel(value: any) {
}
}
class PrettyPrintTranform extends Transform {
export class PinoPrettyTransform extends Transform {
_transform(chunk: any, encoding: string, cb: TransformCallback) {
let value: any;
try {
value = JSON.parse(chunk.toString());
} catch (e) {
process.stdout.write(chunk.toString() + "\n");
return cb();
return cb(undefined, chunk.toString() + "\n");
}
const line = formatter(value);
if (!line) {
return cb();
}
process.stdout.write(line + "\n");
cb();
cb(undefined, line + "\n");
}
}
pump(process.stdin, split(), new PrettyPrintTranform());
export default class PrettyCommand extends Command {
static description = "Transforms sprinklers3 log output into a pretty, colorized format";
async run(): Promise<any> {
pump(process.stdin, split(), new PinoPrettyTransform(), process.stdout);
}
}

33
server/commands/serve.ts

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
import { Command } from "@oclif/command";
import * as http from "http";
import * as WebSocket from "ws";
import { createApp, ServerState, WebSocketApi } from "../";
import log from "@common/logger";
export default class ServeCommand extends Command {
static description = "Serves the sprinklers3 backend";
async run(): Promise<any> {
const state = new ServerState();
const app = createApp(state);
const webSocketApi = new WebSocketApi(state);
const port = +(process.env.PORT || 8080);
const host = process.env.HOST || "0.0.0.0";
const server = new http.Server(app);
const webSocketServer = new WebSocket.Server({ server });
webSocketApi.listen(webSocketServer);
try {
await state.start();
server.listen(port, host, () => {
log.info(`listening at ${host}:${port}`);
});
} catch (err) {
log.error({ err }, "error starting server");
}
}
}

18
server/state.ts

@ -21,13 +21,25 @@ export class ServerState { @@ -21,13 +21,25 @@ export class ServerState {
this.database = new Database();
}
async start() {
async startDatabase() {
await this.database.connect();
await this.database.createAll();
logger.info("created database and tables");
logger.info("connected to database");
if (process.env.INSERT_TEST_DATA) {
await this.database.insertTestData();
logger.info("inserted test data");
}
}
async startMqtt() {
this.mqttClient.username = SUPERUSER;
this.mqttClient.password = await generateSuperuserToken();
this.mqttClient.start();
}
async start() {
await Promise.all([
this.startDatabase(), this.startMqtt(),
]);
}
}

179
yarn.lock

@ -39,6 +39,60 @@ @@ -39,6 +39,60 @@
version "1.7.2"
resolved "https://registry.yarnpkg.com/@most/prelude/-/prelude-1.7.2.tgz#be4ed406518d4c8c220e45c39fa7251365425b73"
"@oclif/command@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.5.0.tgz#d5276a19506349fff0254b0dd98e3b8a2bd971aa"
dependencies:
"@oclif/errors" "^1.1.2"
"@oclif/parser" "^3.6.0"
debug "^3.1.0"
semver "^5.5.0"
"@oclif/config@^1.7.4":
version "1.7.4"
resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.7.4.tgz#5b7f779534a339de8c62a863b12f5740b15c41f5"
dependencies:
debug "^3.1.0"
tslib "^1.9.3"
"@oclif/errors@^1.1.2", "@oclif/errors@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.2.0.tgz#4166952699724c25af2ab4528fe223e930655e72"
dependencies:
clean-stack "^1.3.0"
fs-extra "^7.0.0"
indent-string "^3.2.0"
strip-ansi "^4.0.0"
wrap-ansi "^3.0.1"
"@oclif/linewrap@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91"
"@oclif/parser@^3.6.0":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.6.1.tgz#dd0ad29d9178d75a2de30314874a6167675925ed"
dependencies:
"@oclif/linewrap" "^1.0.0"
chalk "^2.4.1"
tslib "^1.9.3"
"@oclif/plugin-help@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-2.1.1.tgz#5bce32a8a9795827e4f0c6f18c3ff30010130e18"
dependencies:
"@oclif/command" "^1.5.0"
chalk "^2.4.1"
indent-string "^3.2.0"
lodash.template "^4.4.0"
string-width "^2.1.1"
widest-line "^2.0.0"
wrap-ansi "^4.0.0"
"@oclif/screen@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-1.0.2.tgz#c9d7c84b0ea60ecec8dd7a9b22c012ba9967aed8"
"@types/async@^2.0.49":
version "2.0.49"
resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.49.tgz#92e33d13f74c895cb9a7f38ba97db8431ed14bc0"
@ -437,7 +491,7 @@ ansi-colors@^3.0.0: @@ -437,7 +491,7 @@ ansi-colors@^3.0.0:
version "3.0.5"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.0.5.tgz#cb9dc64993b64fd6945485f797fc3853137d9a7b"
ansi-escapes@^3.0.0:
ansi-escapes@^3.0.0, ansi-escapes@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
@ -463,6 +517,10 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: @@ -463,6 +517,10 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
ansicolors@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@ -1083,6 +1141,13 @@ capture-stack-trace@^1.0.0: @@ -1083,6 +1141,13 @@ capture-stack-trace@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d"
cardinal@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505"
dependencies:
ansicolors "~0.3.2"
redeyed "~2.1.0"
case-sensitive-paths-webpack-plugin@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.2.tgz#c899b52175763689224571dad778742e133f0192"
@ -1197,6 +1262,10 @@ clean-css@4.2.x: @@ -1197,6 +1262,10 @@ clean-css@4.2.x:
dependencies:
source-map "~0.6.0"
clean-stack@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31"
cli-boxes@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
@ -1217,6 +1286,29 @@ cli-highlight@^1.2.3: @@ -1217,6 +1286,29 @@ cli-highlight@^1.2.3:
parse5 "^3.0.3"
yargs "^10.0.3"
cli-ux@^4.8.1:
version "4.8.1"
resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-4.8.1.tgz#aaaf3d9f0d48310955a208467800325fdeb67b7f"
dependencies:
"@oclif/errors" "^1.2.0"
"@oclif/linewrap" "^1.0.0"
"@oclif/screen" "^1.0.2"
ansi-styles "^3.2.1"
cardinal "^2.1.1"
chalk "^2.4.1"
clean-stack "^1.3.0"
extract-stack "^1.0.0"
fs-extra "^7.0.0"
hyperlinker "^1.0.0"
indent-string "^3.2.0"
is-wsl "^1.1.0"
lodash "^4.17.10"
password-prompt "^1.0.7"
semver "^5.5.1"
strip-ansi "^4.0.0"
supports-color "^5.5.0"
supports-hyperlinks "^1.0.1"
cli-width@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
@ -2078,7 +2170,7 @@ eslint-scope@^4.0.0: @@ -2078,7 +2170,7 @@ eslint-scope@^4.0.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
esprima@^4.0.0:
esprima@^4.0.0, esprima@~4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@ -2281,6 +2373,10 @@ extglob@^2.0.4: @@ -2281,6 +2373,10 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
extract-stack@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/extract-stack/-/extract-stack-1.0.0.tgz#b97acaf9441eea2332529624b732fc5a1c8165fa"
extract-zip@^1.6.5:
version "1.6.7"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9"
@ -2577,6 +2673,14 @@ fs-extra@^1.0.0: @@ -2577,6 +2673,14 @@ fs-extra@^1.0.0:
jsonfile "^2.1.0"
klaw "^1.0.0"
fs-extra@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-minipass@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
@ -2835,6 +2939,10 @@ has-cors@1.1.0: @@ -2835,6 +2939,10 @@ has-cors@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@ -3057,6 +3165,10 @@ https-browserify@^1.0.0: @@ -3057,6 +3165,10 @@ https-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
hyperlinker@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e"
iconv-lite@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
@ -3146,6 +3258,10 @@ indent-string@^2.1.0: @@ -3146,6 +3258,10 @@ indent-string@^2.1.0:
dependencies:
repeating "^2.0.0"
indent-string@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
@ -3655,6 +3771,12 @@ jsonfile@^2.1.0: @@ -3655,6 +3771,12 @@ jsonfile@^2.1.0:
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
optionalDependencies:
graceful-fs "^4.1.6"
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@ -3898,7 +4020,7 @@ lodash.tail@^4.1.1: @@ -3898,7 +4020,7 @@ lodash.tail@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
lodash.template@^4.2.4:
lodash.template@^4.2.4, lodash.template@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
dependencies:
@ -4891,6 +5013,13 @@ pascalcase@^0.1.1: @@ -4891,6 +5013,13 @@ pascalcase@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
password-prompt@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/password-prompt/-/password-prompt-1.0.7.tgz#8e27748d3400bc9c9140d5ade705dfb7aeb7d91a"
dependencies:
ansi-escapes "^3.1.0"
cross-spawn "^6.0.5"
path-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
@ -5810,6 +5939,12 @@ redent@^1.0.0: @@ -5810,6 +5939,12 @@ redent@^1.0.0:
indent-string "^2.1.0"
strip-indent "^1.0.1"
redeyed@~2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b"
dependencies:
esprima "~4.0.0"
reflect-metadata@^0.1.12:
version "0.1.12"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2"
@ -6173,7 +6308,7 @@ semver-diff@^2.0.0: @@ -6173,7 +6308,7 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0:
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0, semver@^5.5.1:
version "5.5.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
@ -6699,12 +6834,19 @@ supports-color@^2.0.0: @@ -6699,12 +6834,19 @@ supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0:
supports-color@^5.0.0, supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
dependencies:
has-flag "^3.0.0"
supports-hyperlinks@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7"
dependencies:
has-flag "^2.0.0"
supports-color "^5.0.0"
svg2png@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/svg2png/-/svg2png-3.0.1.tgz#a2644d68b0231ac00af431aa163714ff17106447"
@ -6915,7 +7057,7 @@ ts-loader@^4.5.0: @@ -6915,7 +7057,7 @@ ts-loader@^4.5.0:
micromatch "^3.1.4"
semver "^5.0.1"
tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@ -7003,9 +7145,9 @@ typeorm@^0.2.7: @@ -7003,9 +7145,9 @@ typeorm@^0.2.7:
yargonaut "^1.1.2"
yargs "^11.1.0"
typescript@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.3.tgz#4853b3e275ecdaa27f78fda46dc273a7eb7fc1c8"
"typescript@^3.1.0 || >=3.1.0-dev.20180901":
version "3.1.0-dev.20180901"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.0-dev.20180901.tgz#732cbb9ae31e39930bdf05a855868640609b8c83"
ua-parser-js@^0.7.18:
version "0.7.18"
@ -7107,6 +7249,10 @@ unique-string@^1.0.0: @@ -7107,6 +7249,10 @@ unique-string@^1.0.0:
dependencies:
crypto-random-string "^1.0.0"
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@ -7520,6 +7666,21 @@ wrap-ansi@^2.0.0: @@ -7520,6 +7666,21 @@ wrap-ansi@^2.0.0:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba"
dependencies:
string-width "^2.1.1"
strip-ansi "^4.0.0"
wrap-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-4.0.0.tgz#b3570d7c70156159a2d42be5cc942e957f7b1131"
dependencies:
ansi-styles "^3.2.0"
string-width "^2.1.1"
strip-ansi "^4.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

Loading…
Cancel
Save