From c714867d3d0c43ccbb7ca8fb3ce969207e4d5c04 Mon Sep 17 00:00:00 2001 From: James Ward Date: Sat, 19 Sep 2020 04:02:03 -0400 Subject: [PATCH] fix: ensure browser builds don't include any non-browser modules (#6743) currently we pull in BetterSqlite3Driver, SqliteDriver, and a few other drivers & files that aren't possible to use in a browser context. this change adds some more browser compatibility features so webpack builds targeted at browsers will be able to complete closes #6739 --- gulpfile.ts | 19 ++++++++++--- package.json | 5 ++++ src/connection/ConnectionOptionsReader.ts | 5 ++-- ...serDirectoryExportedClassesLoader.template | 22 +++++++++++++++ .../BrowserDisabledDriversDummy.template | 28 +++++++++++++++++-- src/platform/BrowserPlatformTools.template | 13 ++++++--- src/platform/PlatformTools.ts | 10 +++++++ 7 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 src/platform/BrowserDirectoryExportedClassesLoader.template diff --git a/gulpfile.ts b/gulpfile.ts index a0ba65cc98..7d0fbeb05d 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -70,6 +70,15 @@ export class Gulpfile { .pipe(gulp.dest("./build/browser/src")); } + /** + * Replaces PlatformTools with browser-specific implementation called BrowserPlatformTools. + */ + @Task() + browserCopyDirectoryExportedClassesLoader() { + return gulp.src("./src/platform/BrowserDirectoryExportedClassesLoader.template") + .pipe(rename("BrowserDirectoryExportedClassesLoader.ts")) + .pipe(gulp.dest("./build/browser/src/platform")); + } /** * Replaces PlatformTools with browser-specific implementation called BrowserPlatformTools. */ @@ -97,7 +106,10 @@ export class Gulpfile { "lib": ["es5", "es6", "dom"], typescript: require("typescript") }); - const tsResult = gulp.src(["./build/browser/src/**/*.ts", "./node_modules/reflect-metadata/**/*.d.ts", "./node_modules/@types/**/*.ts"]) + const tsResult = gulp.src([ + "./build/browser/src/**/*.ts", + "./node_modules/reflect-metadata/**/*.d.ts" + ]) .pipe(sourcemaps.init()) .pipe(tsProject()); @@ -151,8 +163,7 @@ export class Gulpfile { typescript: require("typescript") }); const tsResult = gulp.src([ - "./src/**/*.ts", - "./node_modules/@types/**/*.ts", + "./src/**/*.ts" ]) .pipe(sourcemaps.init()) .pipe(tsProject()); @@ -231,7 +242,7 @@ export class Gulpfile { package() { return [ "clean", - ["browserCopySources", "browserCopyPlatformTools", "browserCopyDisabledDriversDummy"], + ["browserCopySources", "browserCopyPlatformTools", "browserCopyDisabledDriversDummy", "browserCopyDirectoryExportedClassesLoader"], ["packageCompile", "browserCompile"], "packageMoveCompiledFiles", [ diff --git a/package.json b/package.json index 0c9d3d620d..60b1a0fe02 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ }, "main": "./index.js", "browser": { + "./browser/driver/aurora-data-api/AuroraDataApiDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/driver/cockroachdb/CockroachDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/postgres/PostgresDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/oracle/OracleDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sap/SapDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js", @@ -20,6 +22,9 @@ "./browser/driver/mongodb/MongoQueryRunner.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/entity-manager/MongoEntityManager.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/repository/MongoRepository.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/driver/sqlite/SqliteDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/driver/better-sqlite3/BetterSqlite3Driver.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/util/DirectoryExportedClassesLoader.js": "./browser/platform/BrowserDirectoryExportedClassesLoader.js", "./index.js": "./browser/index.js" }, "repository": { diff --git a/src/connection/ConnectionOptionsReader.ts b/src/connection/ConnectionOptionsReader.ts index b995eba565..997c240554 100644 --- a/src/connection/ConnectionOptionsReader.ts +++ b/src/connection/ConnectionOptionsReader.ts @@ -1,4 +1,3 @@ -import dotenv from "dotenv"; import appRootPath from "app-root-path"; import {ConnectionOptions} from "./ConnectionOptions"; import {PlatformTools} from "../platform/PlatformTools"; @@ -95,9 +94,9 @@ export class ConnectionOptionsReader { // if .env file found then load all its variables into process.env using dotenv package if (foundFileFormat === "env") { - dotenv.config({ path: this.baseFilePath }); + PlatformTools.dotenv(this.baseFilePath); } else if (PlatformTools.fileExist(".env")) { - dotenv.config({ path: ".env" }); + PlatformTools.dotenv(".env"); } // Determine config file name diff --git a/src/platform/BrowserDirectoryExportedClassesLoader.template b/src/platform/BrowserDirectoryExportedClassesLoader.template new file mode 100644 index 0000000000..39fe932a7b --- /dev/null +++ b/src/platform/BrowserDirectoryExportedClassesLoader.template @@ -0,0 +1,22 @@ +/** + * Dummy functions for replacement via `package.json` in browser builds. + * + * If we don't include these functions typeorm will throw an error on runtime + * as well as during webpack builds. + */ + +import {Logger} from "../logger/Logger"; + +/** + * Loads all exported classes from the given directory. + */ +export function importClassesFromDirectories(logger: Logger, directories: string[], formats = [".js", ".cjs", ".ts"]): Function[] { + return []; +} + +/** + * Loads all json files from the given directory. + */ +export function importJsonsFromDirectories(directories: string[], format = ".json"): any[] { + return []; +} diff --git a/src/platform/BrowserDisabledDriversDummy.template b/src/platform/BrowserDisabledDriversDummy.template index 25c8cc2934..9b34705886 100644 --- a/src/platform/BrowserDisabledDriversDummy.template +++ b/src/platform/BrowserDisabledDriversDummy.template @@ -3,8 +3,8 @@ * Using those classes reduces the build size by one third. * * If we don't include those dummy classes (and just disable the driver import - * with `false` in `package.json`) typeorm will throw an error on runtime, - * even if those driver are not used. + * with `false` in `package.json`) typeorm will throw an error on runtime and + * during webpack builds even if those driver are not used. */ /** @@ -37,6 +37,18 @@ export class MongoRepository {} */ export class PostgresDriver {} +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class AuroraDataApiDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class CockroachDriver {} + /** * DO NOT IMPORT THIS CLASS - * This is a dummy class for replacement via `package.json` in browser builds @@ -66,3 +78,15 @@ export class MysqlDriver {} * This is a dummy class for replacement via `package.json` in browser builds */ export class OracleDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class SqliteDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class BetterSqlite3Driver {} diff --git a/src/platform/BrowserPlatformTools.template b/src/platform/BrowserPlatformTools.template index 216150aaa0..72295f27d3 100644 --- a/src/platform/BrowserPlatformTools.template +++ b/src/platform/BrowserPlatformTools.template @@ -75,6 +75,11 @@ export class PlatformTools { return false; } + static dotenv(pathStr: string): void { + if (this.type === "browser") + throw new Error(`This option/function is not supported in the browser environment. Failed operation: dotenv.config({ path: "${pathStr}" }).`); + } + /** * Gets environment variable. */ @@ -89,7 +94,7 @@ export class PlatformTools { throw new Error(`This option/function is not supported in the browser environment. Failed operation: fs.readFileSync("${filename}").`); return null; } - + static appendFileSync(filename: string, data: any) { if (this.type === "browser") throw new Error(`This option/function is not supported in the browser environment. Failed operation: fs.appendFileSync("${filename}").`); @@ -125,11 +130,11 @@ export class PlatformTools { static logError(prefix: string, error: any) { console.error(prefix + " ", error); } - + static logWarn(prefix: string, warning: any) { console.warn(prefix + " ", warning); } - + static log(message: string) { console.log(message); } @@ -165,4 +170,4 @@ if (typeof window !== "undefined") { // NativeScript uses global, not window if (typeof global !== "undefined") { global.Buffer = require("buffer/").Buffer; -} \ No newline at end of file +} diff --git a/src/platform/PlatformTools.ts b/src/platform/PlatformTools.ts index a43accfe6c..9d75d8a479 100644 --- a/src/platform/PlatformTools.ts +++ b/src/platform/PlatformTools.ts @@ -1,5 +1,6 @@ import * as path from "path"; import * as fs from "fs"; +import dotenv from "dotenv"; import chalk from "chalk"; import {highlight, Theme} from "cli-highlight"; @@ -181,6 +182,15 @@ export class PlatformTools { }); } + /** + * Loads a dotenv file into the environment variables. + * + * @param path The file to load as a dotenv configuration + */ + static dotenv(pathStr: string): void { + dotenv.config({ path: pathStr }); + } + /** * Gets environment variable. */