feat: Use oclif cli for server; clean up webpack config
This commit is contained in:
		
							parent
							
								
									cbf1285d5d
								
							
						
					
					
						commit
						46f4b9d14a
					
				
							
								
								
									
										9
									
								
								bin/sprinklers3
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										9
									
								
								bin/sprinklers3
									
									
									
									
									
										Executable file
									
								
							@ -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);
 | 
			
		||||
@ -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.",
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
const validEnvs = ["production", "development"];
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
      }, {
 | 
			
		||||
        // 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
 | 
			
		||||
 | 
			
		||||
@ -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");
 | 
			
		||||
 | 
			
		||||
const sassConfig = {
 | 
			
		||||
  loader: require.resolve("sass-loader"),
 | 
			
		||||
  options: {}
 | 
			
		||||
};
 | 
			
		||||
  // 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 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 => {
 | 
			
		||||
      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 => {
 | 
			
		||||
          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 => {
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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 => {
 | 
			
		||||
        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 => {
 | 
			
		||||
        "@common": paths.commonDir
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    module: {
 | 
			
		||||
      rules: rules(env)
 | 
			
		||||
    },
 | 
			
		||||
    module: { rules },
 | 
			
		||||
    plugins: plugins,
 | 
			
		||||
    optimization: {
 | 
			
		||||
      namedModules: isProd
 | 
			
		||||
@ -268,4 +258,6 @@ const getConfig = (module.exports = env => {
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = getConfig;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										126
									
								
								common/browserLogger.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								common/browserLogger.ts
									
									
									
									
									
										Normal file
									
								
							@ -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
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								common/logger.ts
									
									
									
									
									
								
							@ -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
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								package.json
									
									
									
									
									
								
							@ -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 @@
 | 
			
		||||
    "lint": "run-p lint:*"
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
    "paths.js",
 | 
			
		||||
    "dist",
 | 
			
		||||
    "public"
 | 
			
		||||
  ],
 | 
			
		||||
@ -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 @@
 | 
			
		||||
    "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",
 | 
			
		||||
 | 
			
		||||
@ -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++) {
 | 
			
		||||
 | 
			
		||||
@ -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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								server/commands/manage.ts
									
									
									
									
									
										Normal file
									
								
							@ -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.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								server/commands/serve.ts
									
									
									
									
									
										Normal file
									
								
							@ -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");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -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
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								yarn.lock
									
									
									
									
									
								
							@ -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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
    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:
 | 
			
		||||
    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:
 | 
			
		||||
    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:
 | 
			
		||||
    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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
    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:
 | 
			
		||||
  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:
 | 
			
		||||
  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:
 | 
			
		||||
    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:
 | 
			
		||||
    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:
 | 
			
		||||
  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:
 | 
			
		||||
    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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user