Added docker-compose support
This commit is contained in:
		
							parent
							
								
									79ff1e8ff9
								
							
						
					
					
						commit
						9be28477ed
					
				
							
								
								
									
										31
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -1,13 +1,32 @@ | |||||||
|  | FROM node:alpine as builder | ||||||
|  | 
 | ||||||
|  | RUN apk add yarn \ | ||||||
|  |     python \ | ||||||
|  |     make \ | ||||||
|  |     g++ | ||||||
|  | 
 | ||||||
|  | WORKDIR /app/ | ||||||
|  | 
 | ||||||
|  | COPY package.json yarn.lock /app/ | ||||||
|  | RUN yarn install --frozen-lockfile | ||||||
|  | 
 | ||||||
|  | COPY tslint.json /app | ||||||
|  | COPY app/ /app/app | ||||||
|  | COPY common/ /app/common | ||||||
|  | COPY server/ /app/server | ||||||
|  | 
 | ||||||
|  | RUN yarn build | ||||||
|  | 
 | ||||||
|  | RUN yarn install --frozen-lockfile --production | ||||||
|  | 
 | ||||||
| FROM node:alpine | FROM node:alpine | ||||||
| 
 | 
 | ||||||
| RUN npm install --global yarn |  | ||||||
| 
 |  | ||||||
| ADD package.json yarn.lock /app/ |  | ||||||
| WORKDIR /app/ | WORKDIR /app/ | ||||||
| RUN yarn install --production |  | ||||||
| 
 | 
 | ||||||
| ADD dist/ /app/dist | COPY --from=builder /app/package.json /app/yarn.lock ./ | ||||||
| ADD public/ /app/public | COPY --from=builder /app/node_modules ./node_modules | ||||||
|  | COPY --from=builder /app/dist ./dist | ||||||
|  | COPY --from=builder /app/public ./public | ||||||
| 
 | 
 | ||||||
| EXPOSE 8080 | EXPOSE 8080 | ||||||
| ENTRYPOINT [ "npm", "run", "start" ] | ENTRYPOINT [ "npm", "run", "start" ] | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ import { observer } from "mobx-react"; | |||||||
| import { createViewModel, IViewModel } from "mobx-utils"; | import { createViewModel, IViewModel } from "mobx-utils"; | ||||||
| import * as React from "react"; | import * as React from "react"; | ||||||
| import { RouteComponentProps } from "react-router"; | import { RouteComponentProps } from "react-router"; | ||||||
| import { Button, CheckboxProps, Form, Input, InputOnChangeData, Menu, Modal, Segment } from "semantic-ui-react"; | import { Button, CheckboxProps, Form, Input, InputOnChangeData, Menu, Modal } from "semantic-ui-react"; | ||||||
| 
 | 
 | ||||||
| import { ProgramSequenceView, ScheduleView } from "@app/components"; | import { ProgramSequenceView, ScheduleView } from "@app/components"; | ||||||
| import * as rp from "@app/routePaths"; | import * as rp from "@app/routePaths"; | ||||||
|  | |||||||
| @ -11,8 +11,8 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin"); | |||||||
| const HappyPack = require("happypack"); | const HappyPack = require("happypack"); | ||||||
| const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); | const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); | ||||||
| 
 | 
 | ||||||
| const {getClientEnvironment} = require("../env"); | const {getClientEnvironment} = require("../common/env"); | ||||||
| const paths = require("../paths"); | const paths = require("../common/paths"); | ||||||
| 
 | 
 | ||||||
| // Webpack uses `publicPath` to determine where the app is being served from.
 | // 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.
 | // It requires a trailing slash, or the file assets will get an incorrect path.
 | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										26
									
								
								build.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | 
 | ||||||
|  | set -e | ||||||
|  | 
 | ||||||
|  | IMAGE_NAME="amikhalev/sprinklers3" | ||||||
|  | BUILD_IMAGE="$IMAGE_NAME:build" | ||||||
|  | DIST_IMAGE="$IMAGE_NAME:dist" | ||||||
|  | EXTRACT_CONTAINER="extract-$RANDOM" | ||||||
|  | BUILD_DIR="." | ||||||
|  | 
 | ||||||
|  | echo "Cleaning build files" | ||||||
|  | rm -rf ./build ./dist ./public | ||||||
|  | 
 | ||||||
|  | echo "Building build image $BUILD_IMAGE" | ||||||
|  | docker build -t "$BUILD_IMAGE" --target builder . | ||||||
|  | 
 | ||||||
|  | echo "Extracting build image using container $EXTRACT_CONTAINER" | ||||||
|  | mkdir -p ./build | ||||||
|  | cp package.json yarn.lock "$BUILD_DIR" | ||||||
|  | docker container create --name "$EXTRACT_CONTAINER" "$BUILD_IMAGE" | ||||||
|  | docker container cp "$EXTRACT_CONTAINER:/app/dist" "$BUILD_DIR/dist" | ||||||
|  | docker container cp "$EXTRACT_CONTAINER:/app/public" "$BUILD_DIR/public" | ||||||
|  | docker container rm -f "$EXTRACT_CONTAINER" | ||||||
|  | 
 | ||||||
|  | echo "Building dist image $DIST_IMAGE" | ||||||
|  | docker build -t "$DIST_IMAGE" . | ||||||
| @ -1,4 +1,8 @@ | |||||||
| export class Duration { | export class Duration { | ||||||
|  |     static fromSeconds(seconds: number): Duration { | ||||||
|  |         return new Duration(Math.floor(seconds / 60), seconds % 60); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     minutes: number = 0; |     minutes: number = 0; | ||||||
|     seconds: number = 0; |     seconds: number = 0; | ||||||
| 
 | 
 | ||||||
| @ -7,10 +11,6 @@ export class Duration { | |||||||
|         this.seconds = seconds; |         this.seconds = seconds; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static fromSeconds(seconds: number): Duration { |  | ||||||
|         return new Duration(Math.floor(seconds / 60), seconds % 60); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     toSeconds(): number { |     toSeconds(): number { | ||||||
|         return this.minutes * 60 + this.seconds; |         return this.minutes * 60 + this.seconds; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ if (!NODE_ENV) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
 | ||||||
| var dotenvFiles = [ | const dotenvFiles = [ | ||||||
|   `${paths.dotenv}.${NODE_ENV}.local`, |   `${paths.dotenv}.${NODE_ENV}.local`, | ||||||
|   `${paths.dotenv}.${NODE_ENV}`, |   `${paths.dotenv}.${NODE_ENV}`, | ||||||
|   // Don"t include `.env.local` for `test` environment
 |   // Don"t include `.env.local` for `test` environment
 | ||||||
| @ -1,5 +1,7 @@ | |||||||
| import * as pino from "pino"; | import * as pino from "pino"; | ||||||
| 
 | 
 | ||||||
|  | // tslint:disable:no-console
 | ||||||
|  | 
 | ||||||
| type Level = "default" | "60" | "50" | "40" | "30" | "20" | "10"; | type Level = "default" | "60" | "50" | "40" | "30" | "20" | "10"; | ||||||
| 
 | 
 | ||||||
| const levels: {[level in Level]: string } = { | const levels: {[level in Level]: string } = { | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ export abstract class SprinklersDevice { | |||||||
|     sectionRunnerConstructor: typeof SectionRunner = SectionRunner; |     sectionRunnerConstructor: typeof SectionRunner = SectionRunner; | ||||||
|     programConstructor: typeof Program = Program; |     programConstructor: typeof Program = Program; | ||||||
| 
 | 
 | ||||||
|     constructor() { |     protected constructor() { | ||||||
|         this.sectionRunner = new (this.sectionRunnerConstructor)(this); |         this.sectionRunner = new (this.sectionRunnerConstructor)(this); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ export type UpdateProgramResponse = Response<"updateProgram", { data: any }>; | |||||||
| export interface WithSection { sectionId: number; } | export interface WithSection { sectionId: number; } | ||||||
| 
 | 
 | ||||||
| export type RunSectionData = WithSection & { duration: number }; | export type RunSectionData = WithSection & { duration: number }; | ||||||
| export type RunSectionReqeust = RunSectionData & WithType<"runSection">; | export type RunSectionRequest = RunSectionData & WithType<"runSection">; | ||||||
| export type RunSectionResponse = Response<"runSection", { runId: number }>; | export type RunSectionResponse = Response<"runSection", { runId: number }>; | ||||||
| 
 | 
 | ||||||
| export type CancelSectionRequest = WithSection & WithType<"cancelSection">; | export type CancelSectionRequest = WithSection & WithType<"cancelSection">; | ||||||
| @ -26,7 +26,7 @@ export interface PauseSectionRunnerData { paused: boolean; } | |||||||
| export type PauseSectionRunnerRequest = PauseSectionRunnerData & WithType<"pauseSectionRunner">; | export type PauseSectionRunnerRequest = PauseSectionRunnerData & WithType<"pauseSectionRunner">; | ||||||
| 
 | 
 | ||||||
| export type Request = RunProgramRequest | CancelProgramRequest | UpdateProgramRequest | | export type Request = RunProgramRequest | CancelProgramRequest | UpdateProgramRequest | | ||||||
|     RunSectionReqeust | CancelSectionRequest | CancelSectionRunIdRequest | PauseSectionRunnerRequest; |     RunSectionRequest | CancelSectionRequest | CancelSectionRunIdRequest | PauseSectionRunnerRequest; | ||||||
| 
 | 
 | ||||||
| export type RequestType = Request["type"]; | export type RequestType = Request["type"]; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								common/sprinklersRpc/mqtt/MqttProgram.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								common/sprinklersRpc/mqtt/MqttProgram.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | import { update } from "serializr"; | ||||||
|  | 
 | ||||||
|  | import * as s from "@common/sprinklersRpc"; | ||||||
|  | import * as schema from "@common/sprinklersRpc/schema"; | ||||||
|  | 
 | ||||||
|  | export class MqttProgram extends s.Program { | ||||||
|  |     onMessage(payload: string, topic: string | undefined) { | ||||||
|  |         if (topic === "running") { | ||||||
|  |             this.running = (payload === "true"); | ||||||
|  |         } else if (topic == null) { | ||||||
|  |             this.updateFromJSON(JSON.parse(payload)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     updateFromJSON(json: any) { | ||||||
|  |         update(schema.program, this, json); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								common/sprinklersRpc/mqtt/MqttSection.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								common/sprinklersRpc/mqtt/MqttSection.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | import { update } from "serializr"; | ||||||
|  | 
 | ||||||
|  | import * as s from "@common/sprinklersRpc"; | ||||||
|  | import * as schema from "@common/sprinklersRpc/schema"; | ||||||
|  | 
 | ||||||
|  | export class MqttSection extends s.Section { | ||||||
|  |     onMessage(payload: string, topic: string | undefined) { | ||||||
|  |         if (topic === "state") { | ||||||
|  |             this.state = (payload === "true"); | ||||||
|  |         } else if (topic == null) { | ||||||
|  |             this.updateFromJSON(JSON.parse(payload)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     updateFromJSON(json: any) { | ||||||
|  |         update(schema.section, this, json); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								common/sprinklersRpc/mqtt/MqttSectionRunner.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								common/sprinklersRpc/mqtt/MqttSectionRunner.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | import { update } from "serializr"; | ||||||
|  | 
 | ||||||
|  | import * as s from "@common/sprinklersRpc"; | ||||||
|  | import * as schema from "@common/sprinklersRpc/schema"; | ||||||
|  | 
 | ||||||
|  | export class MqttSectionRunner extends s.SectionRunner { | ||||||
|  |     onMessage(payload: string) { | ||||||
|  |         this.updateFromJSON(JSON.parse(payload)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     updateFromJSON(json: any) { | ||||||
|  |         update(schema.sectionRunner, this, json); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,14 +1,16 @@ | |||||||
| import { autorun, observable } from "mobx"; | import { autorun, observable } from "mobx"; | ||||||
| import * as mqtt from "mqtt"; | import * as mqtt from "mqtt"; | ||||||
| import { update } from "serializr"; |  | ||||||
| 
 | 
 | ||||||
| import logger from "@common/logger"; | import logger from "@common/logger"; | ||||||
| import * as s from "@common/sprinklersRpc"; | import * as s from "@common/sprinklersRpc"; | ||||||
| import * as requests from "@common/sprinklersRpc/deviceRequests"; | import * as requests from "@common/sprinklersRpc/deviceRequests"; | ||||||
| import * as schema from "@common/sprinklersRpc/schema"; |  | ||||||
| import { seralizeRequest } from "@common/sprinklersRpc/schema/requests"; | import { seralizeRequest } from "@common/sprinklersRpc/schema/requests"; | ||||||
| import { getRandomId } from "@common/utils"; | import { getRandomId } from "@common/utils"; | ||||||
| 
 | 
 | ||||||
|  | import { MqttProgram } from "./MqttProgram"; | ||||||
|  | import { MqttSection } from "./MqttSection"; | ||||||
|  | import { MqttSectionRunner } from "./MqttSectionRunner"; | ||||||
|  | 
 | ||||||
| const log = logger.child({ source: "mqtt" }); | const log = logger.child({ source: "mqtt" }); | ||||||
| 
 | 
 | ||||||
| interface WithRid { | interface WithRid { | ||||||
| @ -16,24 +18,24 @@ interface WithRid { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class MqttRpcClient implements s.SprinklersRPC { | export class MqttRpcClient implements s.SprinklersRPC { | ||||||
|  |     get connected(): boolean { | ||||||
|  |         return this.connectionState.isServerConnected || false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static newClientId() { | ||||||
|  |         return "sprinklers3-MqttApiClient-" + getRandomId(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     readonly mqttUri: string; |     readonly mqttUri: string; | ||||||
|     client!: mqtt.Client; |     client!: mqtt.Client; | ||||||
|     @observable connectionState: s.ConnectionState = new s.ConnectionState(); |     @observable connectionState: s.ConnectionState = new s.ConnectionState(); | ||||||
|     devices: Map<string, MqttSprinklersDevice> = new Map(); |     devices: Map<string, MqttSprinklersDevice> = new Map(); | ||||||
| 
 | 
 | ||||||
|     get connected(): boolean { |  | ||||||
|         return this.connectionState.isServerConnected || false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     constructor(mqttUri: string) { |     constructor(mqttUri: string) { | ||||||
|         this.mqttUri = mqttUri; |         this.mqttUri = mqttUri; | ||||||
|         this.connectionState.serverToBroker = false; |         this.connectionState.serverToBroker = false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static newClientId() { |  | ||||||
|         return "sprinklers3-MqttApiClient-" + getRandomId(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     start() { |     start() { | ||||||
|         const clientId = MqttRpcClient.newClientId(); |         const clientId = MqttRpcClient.newClientId(); | ||||||
|         log.info({ mqttUri: this.mqttUri, clientId }, "connecting to mqtt broker with client id"); |         log.info({ mqttUri: this.mqttUri, clientId }, "connecting to mqtt broker with client id"); | ||||||
| @ -281,41 +283,3 @@ class MqttSprinklersDevice extends s.SprinklersDevice { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ResponseCallback = (response: requests.Response) => void; | type ResponseCallback = (response: requests.Response) => void; | ||||||
| 
 |  | ||||||
| class MqttSection extends s.Section { |  | ||||||
|     onMessage(payload: string, topic: string | undefined) { |  | ||||||
|         if (topic === "state") { |  | ||||||
|             this.state = (payload === "true"); |  | ||||||
|         } else if (topic == null) { |  | ||||||
|             this.updateFromJSON(JSON.parse(payload)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     updateFromJSON(json: any) { |  | ||||||
|         update(schema.section, this, json); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class MqttProgram extends s.Program { |  | ||||||
|     onMessage(payload: string, topic: string | undefined) { |  | ||||||
|         if (topic === "running") { |  | ||||||
|             this.running = (payload === "true"); |  | ||||||
|         } else if (topic == null) { |  | ||||||
|             this.updateFromJSON(JSON.parse(payload)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     updateFromJSON(json: any) { |  | ||||||
|         update(schema.program, this, json); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class MqttSectionRunner extends s.SectionRunner { |  | ||||||
|     onMessage(payload: string) { |  | ||||||
|         this.updateFromJSON(JSON.parse(payload)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     updateFromJSON(json: any) { |  | ||||||
|         update(schema.sectionRunner, this, json); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -1,6 +1,10 @@ | |||||||
| import { observable } from "mobx"; | import { observable } from "mobx"; | ||||||
| 
 | 
 | ||||||
| export class TimeOfDay { | export class TimeOfDay { | ||||||
|  |     static fromDate(date: Date): TimeOfDay { | ||||||
|  |         return new TimeOfDay(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     readonly hour: number; |     readonly hour: number; | ||||||
|     readonly minute: number; |     readonly minute: number; | ||||||
|     readonly second: number; |     readonly second: number; | ||||||
| @ -12,10 +16,6 @@ export class TimeOfDay { | |||||||
|         this.second = second; |         this.second = second; | ||||||
|         this.millisecond = millisecond; |         this.millisecond = millisecond; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     static fromDate(date: Date): TimeOfDay { |  | ||||||
|         return new TimeOfDay(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export enum Weekday { | export enum Weekday { | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | version: "3" | ||||||
|  | services: | ||||||
|  |   web: | ||||||
|  |     image: "amikhalev/sprinklers3" | ||||||
|  |     build: . | ||||||
|  |     ports: | ||||||
|  |       - "8080:8080" | ||||||
|  |     env_file: | ||||||
|  |       - .env | ||||||
|  |     environment: | ||||||
|  |       - PORT=8080 | ||||||
|  |       - TYPEORM_CONNECTION=postgres | ||||||
|  |       - TYPEORM_HOST=database | ||||||
|  |       - TYPEORM_DATABASE=postgres | ||||||
|  |       - TYPEORM_USERNAME=postgres | ||||||
|  |       - TYPEORM_PASSWORD=8JN4w0UsN5dbjMjNvPe452P2yYOqg5PV | ||||||
|  |       # Must specify JWT_SECRET and MQTT_URL | ||||||
|  | 
 | ||||||
|  |   database: | ||||||
|  |     image: "postgres:11-alpine" | ||||||
|  |     environment: | ||||||
|  |       - POSTGRES_PASSWORD=8JN4w0UsN5dbjMjNvPe452P2yYOqg5PV | ||||||
| @ -8,6 +8,7 @@ | |||||||
|     "clean": "rm -rf ./dist ./build ./public", |     "clean": "rm -rf ./dist ./build ./public", | ||||||
|     "build:app": "NODE_ENV=production webpack --config ./app/webpack.config.js --env prod", |     "build:app": "NODE_ENV=production webpack --config ./app/webpack.config.js --env prod", | ||||||
|     "build:server": "tsc --project server", |     "build:server": "tsc --project server", | ||||||
|  |     "build": "run-p build:*", | ||||||
|     "watch:app": "yarn build:app --watch", |     "watch:app": "yarn build:app --watch", | ||||||
|     "watch:server": "yarn build:server --watch", |     "watch:server": "yarn build:server --watch", | ||||||
|     "start:dev-server": "NODE_ENV=development webpack-dev-server --config ./app/webpack.config.js --env dev", |     "start:dev-server": "NODE_ENV=development webpack-dev-server --config ./app/webpack.config.js --env dev", | ||||||
| @ -41,7 +42,6 @@ | |||||||
|     "express": "^4.16.3", |     "express": "^4.16.3", | ||||||
|     "express-pino-logger": "^3.0.2", |     "express-pino-logger": "^3.0.2", | ||||||
|     "express-promise-router": "^3.0.3", |     "express-promise-router": "^3.0.3", | ||||||
|     "fork-ts-checker-webpack-plugin": "^0.4.3", |  | ||||||
|     "jsonwebtoken": "^8.3.0", |     "jsonwebtoken": "^8.3.0", | ||||||
|     "lodash": "^4.17.10", |     "lodash": "^4.17.10", | ||||||
|     "mobx": "^5.0.3", |     "mobx": "^5.0.3", | ||||||
| @ -54,7 +54,6 @@ | |||||||
|     "reflect-metadata": "^0.1.12", |     "reflect-metadata": "^0.1.12", | ||||||
|     "serializr": "^1.3.0", |     "serializr": "^1.3.0", | ||||||
|     "typeorm": "^0.2.7", |     "typeorm": "^0.2.7", | ||||||
|     "uglify-es": "3.3.9", |  | ||||||
|     "ws": "^6.0.0" |     "ws": "^6.0.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
| @ -84,6 +83,7 @@ | |||||||
|     "favicons-webpack-plugin": "^0.0.9", |     "favicons-webpack-plugin": "^0.0.9", | ||||||
|     "file-loader": "^1.1.11", |     "file-loader": "^1.1.11", | ||||||
|     "font-awesome": "^4.7.0", |     "font-awesome": "^4.7.0", | ||||||
|  |     "fork-ts-checker-webpack-plugin": "^0.4.3", | ||||||
|     "happypack": "^5.0.0", |     "happypack": "^5.0.0", | ||||||
|     "html-webpack-plugin": "^3.2.0", |     "html-webpack-plugin": "^3.2.0", | ||||||
|     "mini-css-extract-plugin": "^0.4.1", |     "mini-css-extract-plugin": "^0.4.1", | ||||||
| @ -114,6 +114,7 @@ | |||||||
|     "tslint": "^5.11.0", |     "tslint": "^5.11.0", | ||||||
|     "tslint-react": "^3.6.0", |     "tslint-react": "^3.6.0", | ||||||
|     "typescript": "^2.9.2", |     "typescript": "^2.9.2", | ||||||
|  |     "uglify-es": "^3.3.9", | ||||||
|     "uglifyjs-webpack-plugin": "^1.2.6", |     "uglifyjs-webpack-plugin": "^1.2.6", | ||||||
|     "url-loader": "^1.0.1", |     "url-loader": "^1.0.1", | ||||||
|     "webpack": "^4.16.2", |     "webpack": "^4.16.2", | ||||||
|  | |||||||
| @ -2,5 +2,3 @@ import * as moduleAlias from "module-alias"; | |||||||
| import * as path from "path"; | import * as path from "path"; | ||||||
| moduleAlias.addAlias("@common", path.resolve(__dirname, "..", "common")); | moduleAlias.addAlias("@common", path.resolve(__dirname, "..", "common")); | ||||||
| moduleAlias.addAlias("@server", __dirname); | moduleAlias.addAlias("@server", __dirname); | ||||||
| moduleAlias.addAlias("env", require.resolve("../env")); |  | ||||||
| moduleAlias.addAlias("paths", require.resolve("../paths")); |  | ||||||
|  | |||||||
| @ -11,4 +11,4 @@ const errorHandler: express.ErrorRequestHandler = | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| export default errorHandler; | export default errorHandler; | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ import { Express } from "express"; | |||||||
| import * as path from "path"; | import * as path from "path"; | ||||||
| import * as serveStatic from "serve-static"; | import * as serveStatic from "serve-static"; | ||||||
| 
 | 
 | ||||||
| import * as paths from "paths"; | import * as paths from "@common/paths"; | ||||||
| 
 | 
 | ||||||
| const index = path.join(paths.publicDir, "index.html"); | const index = path.join(paths.publicDir, "index.html"); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| /* tslint:disable:ordered-imports */ | /* tslint:disable:ordered-imports */ | ||||||
| import "reflect-metadata"; | import "reflect-metadata"; | ||||||
| import "./configureAlias"; | import "./configureAlias"; | ||||||
| import "env"; | import "@common/env"; | ||||||
| import "./configureLogger"; | import "./configureLogger"; | ||||||
| 
 | 
 | ||||||
| import log from "@common/logger"; | import log from "@common/logger"; | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ | |||||||
|       true |       true | ||||||
|     ], |     ], | ||||||
|     "max-classes-per-file": [ |     "max-classes-per-file": [ | ||||||
|       false |       true, 3 | ||||||
|     ], |     ], | ||||||
|     "ordered-imports": true, |     "ordered-imports": true, | ||||||
|     "variable-name": [ |     "variable-name": [ | ||||||
| @ -24,16 +24,13 @@ | |||||||
|     "member-ordering": [ |     "member-ordering": [ | ||||||
|       true, |       true, | ||||||
|       { |       { | ||||||
|         "order": "fields-first" |         "order": "statics-first" | ||||||
|       } |       } | ||||||
|     ], |     ], | ||||||
|     "object-literal-sort-keys": [ |     "object-literal-sort-keys": [ | ||||||
|       false |       false | ||||||
|     ], |     ], | ||||||
|     "no-submodule-imports": false, |     "no-submodule-imports": false, | ||||||
|     "no-unused-variable": [ |  | ||||||
|       true |  | ||||||
|     ], |  | ||||||
|     "jsx-boolean-value": [ true, "never" ], |     "jsx-boolean-value": [ true, "never" ], | ||||||
|     "no-implicit-dependencies": false |     "no-implicit-dependencies": false | ||||||
|   }, |   }, | ||||||
|  | |||||||
| @ -7125,7 +7125,7 @@ ua-parser-js@^0.7.18: | |||||||
|   version "0.7.18" |   version "0.7.18" | ||||||
|   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" |   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" | ||||||
| 
 | 
 | ||||||
| uglify-es@3.3.9, uglify-es@^3.3.4: | uglify-es@^3.3.4, uglify-es@^3.3.9: | ||||||
|   version "3.3.9" |   version "3.3.9" | ||||||
|   resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" |   resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" | ||||||
|   dependencies: |   dependencies: | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user