From 6895ee5d428b6b1d11a3dd55058b3bd17eb1d15d Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Fri, 31 Aug 2018 21:59:06 -0600 Subject: [PATCH] Use typescript project references --- Dockerfile | 1 + Dockerfile.dev | 1 + {common => client}/env.js | 5 +--- client/tsconfig.json | 7 +++++- client/webpack.config.js | 10 ++------ common/sprinklersRpc/schema/requests.ts | 3 ++- common/sprinklersRpc/websocketData.ts | 3 +-- common/tsconfig.json | 8 +++---- package.json | 8 +++---- common/paths.js => paths.js | 4 ++-- server/Database.ts | 2 +- server/configureAlias.ts | 3 ++- server/env.ts | 24 +++++++++++++++++++ server/express/index.ts | 2 +- server/express/serveApp.ts | 3 ++- server/index.ts | 2 +- .../SprinklersDeviceRepository.ts | 2 +- server/repositories/UserRepository.ts | 2 +- server/tsconfig.json | 5 ++++ 19 files changed, 62 insertions(+), 33 deletions(-) rename {common => client}/env.js (95%) rename common/paths.js => paths.js (96%) create mode 100644 server/env.ts diff --git a/Dockerfile b/Dockerfile index a56733d..1432c2d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ COPY package.json yarn.lock /app/ RUN yarn install --frozen-lockfile COPY tslint.json /app +COPY paths.js /app COPY client/ /app/client COPY common/ /app/common COPY server/ /app/server diff --git a/Dockerfile.dev b/Dockerfile.dev index 0cc9aa6..a97a4d2 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -5,6 +5,7 @@ WORKDIR /app/ COPY package.json yarn.lock /app/ RUN yarn install --frozen-lockfile +COPY paths.js /app COPY tslint.json /app EXPOSE 8080 diff --git a/common/env.js b/client/env.js similarity index 95% rename from common/env.js rename to client/env.js index 8b66094..e2ee4ae 100644 --- a/common/env.js +++ b/client/env.js @@ -1,9 +1,6 @@ const fs = require("fs"); const path = require("path"); -const paths = require("./paths"); - -// Make sure that including paths.js after env.js will read .env variables. -delete require.cache[require.resolve("./paths")]; +const paths = require("../paths") const NODE_ENV = process.env.NODE_ENV; if (!NODE_ENV) { diff --git a/client/tsconfig.json b/client/tsconfig.json index f91c3fa..60bc6b8 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -25,5 +25,10 @@ "./client/*" ] } - } + }, + "references": [ + { + "path": "../common" + } + ] } \ No newline at end of file diff --git a/client/webpack.config.js b/client/webpack.config.js index 85719b4..033b6d1 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -11,8 +11,8 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const HappyPack = require("happypack"); const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); -const {getClientEnvironment} = require("../common/env"); -const paths = require("../common/paths"); +const {getClientEnvironment} = require("./env"); +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. @@ -23,15 +23,9 @@ const publicPath = paths.publicPath; 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'; -// Some apps do not use client-side routing with pushState. -// For these, "homepage" can be set to "." to enable relative asset paths. -const shouldUseRelativeAssetPaths = publicPath === "./"; // Get environment variables to inject into our app. const environ = getClientEnvironment(publicUrl); -// Note: defined here because it will be used more than once. -const cssFilename = "static/css/[name].[contenthash:8].css"; - const postCssConfig = { loader: require.resolve("postcss-loader"), options: { diff --git a/common/sprinklersRpc/schema/requests.ts b/common/sprinklersRpc/schema/requests.ts index 12543bb..42bcc56 100644 --- a/common/sprinklersRpc/schema/requests.ts +++ b/common/sprinklersRpc/schema/requests.ts @@ -1,5 +1,6 @@ import { createSimpleSchema, deserialize, ModelSchema, primitive, serialize } from "serializr"; -import * as requests from "../deviceRequests"; + +import * as requests from "@common/sprinklersRpc/deviceRequests"; import * as common from "./common"; export const withType: ModelSchema = createSimpleSchema({ diff --git a/common/sprinklersRpc/websocketData.ts b/common/sprinklersRpc/websocketData.ts index 1cc7197..80cc9d6 100644 --- a/common/sprinklersRpc/websocketData.ts +++ b/common/sprinklersRpc/websocketData.ts @@ -1,6 +1,5 @@ -import * as rpc from "../jsonRpc/index"; - import { IUser } from "@common/httpApi"; +import * as rpc from "@common/jsonRpc/index"; import { Response as ResponseData } from "@common/sprinklersRpc/deviceRequests"; export interface IAuthenticateRequest { diff --git a/common/tsconfig.json b/common/tsconfig.json index 1f03307..5539fa7 100644 --- a/common/tsconfig.json +++ b/common/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "outDir": "../dist/common", "experimentalDecorators": true, "target": "es2017", "lib": [ @@ -10,15 +11,14 @@ ], "module": "commonjs", "strict": true, - "allowJs": true, "baseUrl": "..", + "composite": true, + "declaration": true, "sourceMap": true, + "declarationMap": true, "paths": { "@common/*": [ "./common/*" - ], - "@client/*": [ - "./client/*" ] } }, diff --git a/package.json b/package.json index cb0eb59..57267a6 100644 --- a/package.json +++ b/package.json @@ -3,19 +3,19 @@ "version": "1.0.0", "private": true, "description": "A frontend for mqtt based IoT sprinklers systems", - "main": "dist/server/index.js", + "main": "dist/index.js", "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:server": "tsc --project server", + "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/server/logging/prettyPrint.js", - "start:nodemon": "nodemon --delay 0.5 --exec \"env NODE_ENV=development node . | node dist/server/logging/prettyPrint.js\"", + "start:pretty": "yarn start | node dist/logging/prettyPrint.js", + "start:nodemon": "nodemon --delay 0.5 --exec \"env NODE_ENV=development node . | node dist/logging/prettyPrint.js\"", "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", diff --git a/common/paths.js b/paths.js similarity index 96% rename from common/paths.js rename to paths.js index cfe9a6d..401bee1 100644 --- a/common/paths.js +++ b/paths.js @@ -1,5 +1,5 @@ -const path = require("path"); const fs = require("fs"); +const path = require("path"); const url = require("url"); exports.rootDir = fs.realpathSync(process.cwd()); @@ -8,7 +8,7 @@ const resolveRoot = exports.resolveRoot = (p) => path.resolve(exports.rootDir, p function ensureSlash(p, needsSlash) { const hasSlash = p.endsWith("/"); if (hasSlash && !needsSlash) { - return p.substr(p, p.length - 1); + return p.substr(0, p.length - 1); } else if (!hasSlash && needsSlash) { return `${p}/`; } else { diff --git a/server/Database.ts b/server/Database.ts index 03d9ae3..d6a1936 100644 --- a/server/Database.ts +++ b/server/Database.ts @@ -1,7 +1,7 @@ import * as path from "path"; import { Connection, createConnection, EntityManager, getConnectionOptions, Repository } from "typeorm"; -import logger from "../common/logger"; +import logger from "@common/logger"; import { SprinklersDevice, User } from "./entities"; import { SprinklersDeviceRepository, UserRepository } from "./repositories/"; diff --git a/server/configureAlias.ts b/server/configureAlias.ts index 98c8a45..99cf4f8 100644 --- a/server/configureAlias.ts +++ b/server/configureAlias.ts @@ -1,4 +1,5 @@ import * as moduleAlias from "module-alias"; 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("paths", path.resolve(__dirname, "..", "paths")); diff --git a/server/env.ts b/server/env.ts new file mode 100644 index 0000000..694a4e3 --- /dev/null +++ b/server/env.ts @@ -0,0 +1,24 @@ +import * as fs from "fs"; + +// tslint:disable-next-line:no-var-requires +const paths = require("paths"); + +const NODE_ENV = process.env.NODE_ENV || "development"; + +const dotenvFiles: string[] = [ + `${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) as string[]; + +dotenvFiles.forEach((dotenvFile) => { + if (fs.existsSync(dotenvFile)) { + require("dotenv").config({ + path: dotenvFile, + }); + } +}); diff --git a/server/express/index.ts b/server/express/index.ts index 8e0df2f..5ced086 100644 --- a/server/express/index.ts +++ b/server/express/index.ts @@ -1,7 +1,7 @@ import * as bodyParser from "body-parser"; import * as express from "express"; -import { ServerState } from "../state"; +import { ServerState } from "@server/state"; import createApi from "./api"; import errorHandler from "./errorHandler"; import requestLogger from "./requestLogger"; diff --git a/server/express/serveApp.ts b/server/express/serveApp.ts index 6a4ee16..fa875c6 100644 --- a/server/express/serveApp.ts +++ b/server/express/serveApp.ts @@ -2,7 +2,8 @@ import { Express } from "express"; import * as path from "path"; import * as serveStatic from "serve-static"; -import * as paths from "@common/paths"; +// tslint:disable-next-line:no-var-requires +const paths = require("paths"); const index = path.join(paths.publicDir, "index.html"); diff --git a/server/index.ts b/server/index.ts index e40891b..cfc6981 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,7 +1,7 @@ /* tslint:disable:ordered-imports */ import "reflect-metadata"; import "./configureAlias"; -import "@common/env"; +import "./env"; import "./configureLogger"; import log from "@common/logger"; diff --git a/server/repositories/SprinklersDeviceRepository.ts b/server/repositories/SprinklersDeviceRepository.ts index f43301d..a2ce336 100644 --- a/server/repositories/SprinklersDeviceRepository.ts +++ b/server/repositories/SprinklersDeviceRepository.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from "typeorm"; -import { SprinklersDevice, User } from "../entities"; +import { SprinklersDevice, User } from "@server/entities"; @EntityRepository(SprinklersDevice) export class SprinklersDeviceRepository extends Repository { diff --git a/server/repositories/UserRepository.ts b/server/repositories/UserRepository.ts index a2372a5..2048839 100644 --- a/server/repositories/UserRepository.ts +++ b/server/repositories/UserRepository.ts @@ -1,6 +1,6 @@ import { EntityRepository, FindOneOptions, Repository } from "typeorm"; -import { User } from "../entities"; +import { User } from "@server/entities"; export interface FindUserOptions { devices: boolean; diff --git a/server/tsconfig.json b/server/tsconfig.json index 2e5e43b..8442075 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -26,6 +26,11 @@ ] } }, + "references": [ + { + "path": "../common" + } + ], "include": [ "./**/*.ts" ]