diff --git a/Scripts/Bin/Compile.ts b/Scripts/Bin/Compile.ts index 9e714ba..dbaa044 100644 --- a/Scripts/Bin/Compile.ts +++ b/Scripts/Bin/Compile.ts @@ -1,6 +1,6 @@ import fs from 'fs-extra'; import debug_base from 'debug'; -import webpackCompiler from '../Build/WebpackCompiler'; +import { webpackCompiler } from '../Build/WebpackCompiler'; import { webpackConfig } from '../Build/WebpackConfig'; import { config } from '../Config'; diff --git a/Scripts/Build/CreateConfig.js b/Scripts/Build/CreateConfig.ts similarity index 72% rename from Scripts/Build/CreateConfig.js rename to Scripts/Build/CreateConfig.ts index 95ed574..52930bf 100644 --- a/Scripts/Build/CreateConfig.js +++ b/Scripts/Build/CreateConfig.ts @@ -1,7 +1,13 @@ -const debug = require('debug')('app:build:config'); -const fs = require('fs'); -const path = require('path'); -const pkg = require('../../package.json'); +import debug_base from 'debug'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import pkg from '../../package.json'; +// const pkg = require('../../package.json'); + +// const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const debug = debug_base('app:build:config'); // TODO: load config from environments /* if (process.env.TRAVIS_PULL_REQUEST === false) { @@ -9,7 +15,7 @@ const pkg = require('../../package.json'); env = "production"; } */ -function createConfigFile(callback, environment) { +export function createConfigFile(callback, environment) { const configObj = { version: pkg.version, // dbVersion: 5, @@ -32,12 +38,12 @@ function createConfigFile(callback, environment) { }, }; - const newText = Object.keys(configObj).map(key => `export const ${key} = ${JSON.stringify(configObj[key])};`).join('\n'); + const newText = Object.keys(configObj).map((key) => `export const ${key} = ${JSON.stringify(configObj[key])};`).join('\n'); const pathRel = environment === 'development' ? 'Source/BakedConfig_Dev.ts' : 'Source/BakedConfig_Prod.ts'; const outputPath = path.join(__dirname, '..', '..', pathRel); - const oldText = fs.existsSync(path) ? fs.readFileSync(outputPath, { encoding: 'utf8' }) : null; + const oldText = fs.existsSync(outputPath) ? fs.readFileSync(outputPath, { encoding: 'utf8' }) : null; if (newText != oldText) { fs.writeFile(outputPath, newText, 'utf8', (err) => { if (err) { diff --git a/Scripts/Build/Deploy.js b/Scripts/Build/Deploy.js deleted file mode 100644 index a106aa3..0000000 --- a/Scripts/Build/Deploy.js +++ /dev/null @@ -1,48 +0,0 @@ -const _debug = require("debug"); // eslint-disable-line no-underscore-dangle -const exec = require("child_process").exec; -const {TRAVIS_BRANCH, TRAVIS_PULL_REQUEST, FIREBASE_TOKEN} = process.env; -const debug = _debug("app:build:deploy"); - -const deployToFirebase = (cb) => { - debug("Travis Variables:", { TRAVIS_PULL_REQUEST, TRAVIS_BRANCH }); - if (!!TRAVIS_PULL_REQUEST && TRAVIS_PULL_REQUEST !== "false") { - debug("Skipping Firebase Deploy - Build is a Pull Request"); - return; - } - - if (TRAVIS_BRANCH !== "prod" && TRAVIS_BRANCH !== "stage" && TRAVIS_BRANCH !== "master") { - debug("Skipping Firebase Deploy - Build is a not a Build Branch", TRAVIS_BRANCH); - return; - } - - if (!FIREBASE_TOKEN) { - debug("Error: FIREBASE_TOKEN env variable not found"); - cb("Error: FIREBASE_TOKEN env variable not found", null); - return; - } - - debug("Deploying to Firebase..."); - - exec(`firebase deploy --token ${FIREBASE_TOKEN}`, (error, stdout) => { - if (error !== null) { - if (cb) { - cb(error, null); - return; - } - } - if (cb) { - cb(null, stdout); - } - }); -} - -(function() { - deployToFirebase((err, stdout) => { - if (err || !stdout) { - debug("error deploying to Firebase: ", err); - return; - } - debug(stdout); // log output of firebase cli - debug("\nSuccessfully deployed to Firebase"); - }) -})(); \ No newline at end of file diff --git a/Scripts/Build/Deploy.ts b/Scripts/Build/Deploy.ts new file mode 100644 index 0000000..26e2add --- /dev/null +++ b/Scripts/Build/Deploy.ts @@ -0,0 +1,49 @@ +import debug_base from 'debug'; // eslint-disable-line no-underscore-dangle +import { exec } from 'child_process'; + +const { TRAVIS_BRANCH, TRAVIS_PULL_REQUEST, FIREBASE_TOKEN } = process.env; +const debug = debug_base('app:build:deploy'); + +const deployToFirebase = (cb) => { + debug('Travis Variables:', { TRAVIS_PULL_REQUEST, TRAVIS_BRANCH }); + if (!!TRAVIS_PULL_REQUEST && TRAVIS_PULL_REQUEST !== 'false') { + debug('Skipping Firebase Deploy - Build is a Pull Request'); + return; + } + + if (TRAVIS_BRANCH !== 'prod' && TRAVIS_BRANCH !== 'stage' && TRAVIS_BRANCH !== 'master') { + debug('Skipping Firebase Deploy - Build is a not a Build Branch', TRAVIS_BRANCH); + return; + } + + if (!FIREBASE_TOKEN) { + debug('Error: FIREBASE_TOKEN env variable not found'); + cb('Error: FIREBASE_TOKEN env variable not found', null); + return; + } + + debug('Deploying to Firebase...'); + + exec(`firebase deploy --token ${FIREBASE_TOKEN}`, (error, stdout) => { + if (error !== null) { + if (cb) { + cb(error, null); + return; + } + } + if (cb) { + cb(null, stdout); + } + }); +}; + +(function () { + deployToFirebase((err, stdout) => { + if (err || !stdout) { + debug('error deploying to Firebase: ', err); + return; + } + debug(stdout); // log output of firebase cli + debug('\nSuccessfully deployed to Firebase'); + }); +}()); diff --git a/Scripts/Build/OnSuccess.js b/Scripts/Build/OnSuccess.ts similarity index 100% rename from Scripts/Build/OnSuccess.js rename to Scripts/Build/OnSuccess.ts diff --git a/Scripts/Build/WebpackCompiler.js b/Scripts/Build/WebpackCompiler.js deleted file mode 100644 index 5a29211..0000000 --- a/Scripts/Build/WebpackCompiler.js +++ /dev/null @@ -1,36 +0,0 @@ -const webpack = require("webpack"); -const debug = require("debug")("app:build:webpack-compiler"); -const config = require("../config"); - -function webpackCompiler(webpackConfig, statsFormat) { - statsFormat = statsFormat || config.compiler_stats; - - return new Promise((resolve, reject)=> { - const compiler = webpack(webpackConfig) - - compiler.run((err, stats)=> { - if (err) { - debug("Webpack compiler encountered a fatal error.", err); - return reject(err); - } - - const jsonStats = stats.toJson(); - debug("Webpack compile completed."); - debug(stats.toString(statsFormat)); - - if (jsonStats.errors.length > 0) { - debug("Webpack compiler encountered errors."); - debug(jsonStats.errors.join("\n")); - return reject(new Error("Webpack compiler encountered errors")); - } else if (jsonStats.warnings.length > 0) { - debug("Webpack compiler encountered warnings."); - debug(jsonStats.warnings.join("\n")); - } else { - debug("No errors or warnings encountered."); - } - resolve(jsonStats); - }); - }); -} - -module.exports = webpackCompiler; \ No newline at end of file diff --git a/Scripts/Build/WebpackCompiler.ts b/Scripts/Build/WebpackCompiler.ts new file mode 100644 index 0000000..9f59d43 --- /dev/null +++ b/Scripts/Build/WebpackCompiler.ts @@ -0,0 +1,36 @@ +import webpack from 'webpack'; +import debug_base from 'debug'; +import { config } from '../Config'; + +const debug = debug_base('app:build:webpack-compiler'); + +export function webpackCompiler(webpackConfig, statsFormat?): Promise { + statsFormat = statsFormat || config.compiler_stats; + + return new Promise((resolve, reject) => { + const compiler = webpack(webpackConfig); + + compiler.run((err, stats) => { + if (err) { + debug('Webpack compiler encountered a fatal error.', err); + return reject(err); + } + + const jsonStats = stats.toJson(); + debug('Webpack compile completed.'); + debug(stats.toString(statsFormat)); + + if (jsonStats.errors.length > 0) { + debug('Webpack compiler encountered errors.'); + debug(jsonStats.errors.join('\n')); + return reject(new Error('Webpack compiler encountered errors')); + } if (jsonStats.warnings.length > 0) { + debug('Webpack compiler encountered warnings.'); + debug(jsonStats.warnings.join('\n')); + } else { + debug('No errors or warnings encountered.'); + } + resolve(jsonStats); + }); + }); +} diff --git a/Scripts/Build/WebpackConfig.ts b/Scripts/Build/WebpackConfig.ts index 3dcffba..2292581 100644 --- a/Scripts/Build/WebpackConfig.ts +++ b/Scripts/Build/WebpackConfig.ts @@ -8,6 +8,8 @@ import fs from 'fs'; import HardSourceWebpackPlugin from 'hard-source-webpack-plugin'; import SpriteLoaderPlugin from 'svg-sprite-loader/plugin'; import { WebpackStringReplacer } from 'webpack-string-replacer'; +// import { CE } from 'js-vextensions'; +import { CE } from 'js-vextensions/Source'; // temp; require source, thus ts-node compiles to commonjs (fix for that ts-node doesn't support es2015-modules) import { config } from '../Config'; import { npmPatch_replacerConfig } from './NPMPatches'; import { MakeSoWebpackConfigOutputsStats } from './WebpackConfig/OutputStats'; @@ -23,6 +25,15 @@ const { QUICK, USE_TSLOADER, OUTPUT_STATS } = process.env; // const root = path.join(__dirname, '..', '..'); +const ownModules = [ + 'js-vextensions', // js (base) + 'react-vextensions', 'react-vcomponents', 'react-vmenu', 'react-vmessagebox', 'react-vscrollview', 'react-vmarkdown', // +react + 'firebase-feedback', 'firebase-forum', // +firebase + 'mobx-firelink', // +mobx + 'vwebapp-framework', // +framework + 'webpack-runtime-require', // misc +]; + debug('Creating configuration.'); export const webpackConfig: webpack.Configuration = { name: 'client', @@ -49,17 +60,17 @@ export const webpackConfig: webpack.Configuration = { '.mjs', // needed for mobx-sync ], alias: { - // always retrieve these packages from the root node_modules folder (they throw errors if there are multiple instances) [needed for when using "npm link"] + // always retrieve these packages from the root node_modules folder (they have issues if there are multiple instances) [needed for when using "npm link"] react: paths.base('node_modules', 'react'), 'react-dom': paths.base('node_modules', 'react-dom'), firebase: paths.base('node_modules', 'firebase'), - // consolidating for these wouldn't throw errors necessarily, but we do so to keep things tidy (since we know the different versions will be compatible anyway) - 'js-vextensions': paths.base('node_modules', 'js-vextensions'), - 'mobx-firelink': paths.base('node_modules', 'mobx-firelink'), + mobx: paths.base('node_modules', 'mobx'), // consolidating for these, since they have npm-patches applied (and we don't want to have to adjust the match-counts) 'react-beautiful-dnd': paths.base('node_modules', 'react-beautiful-dnd'), immer: paths.base('node_modules', 'immer'), - // mobx: paths.base('node_modules', 'mobx'), // maybe temp; used to try to resolve odd bug with Link->immer.produce, which sets a value within firebase-feedback store + // consolidating for these wouldn't throw errors necessarily, but we do so to keep things tidy (since we know the different versions will be compatible anyway) + // note: just put all own packages here + ...CE(ownModules).ToMap((name) => name, (name) => paths.base('node_modules', name)), }, }, module: { @@ -204,7 +215,9 @@ webpackConfig.module.rules = [ [ '@babel/env', { + // use loose transpilation when possible (makes debugging easier) loose: true, + // don't transpile async/await in dev-mode (makes debugging easier) exclude: DEV ? ['babel-plugin-transform-async-to-generator', 'babel-plugin-transform-regenerator'] : [], // targets: {esmodules: true}, // target es2015 targets: { node: '6.5' }, // target es2015 diff --git a/Scripts/Config.ts b/Scripts/Config.ts index 5468e20..0c6bd9e 100644 --- a/Scripts/Config.ts +++ b/Scripts/Config.ts @@ -1,8 +1,10 @@ -import path from 'path'; import debug_base from 'debug'; -import { argv } from 'yargs'; import ip from 'ip'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { argv } from 'yargs'; +// const __dirname = path.dirname(fileURLToPath(import.meta.url)); const { NODE_ENV, PORT, USE_TSLOADER, BASENAME } = process.env; const debug = debug_base('app:config'); diff --git a/Scripts/Server.ts b/Scripts/Server.ts index cf97d27..f2a5a8e 100644 --- a/Scripts/Server.ts +++ b/Scripts/Server.ts @@ -2,8 +2,13 @@ import express from 'express'; import debug_base from 'debug'; import webpack from 'webpack'; import devMiddleware from 'webpack-dev-middleware'; -import { webpackConfig } from './Build/WebpackConfig'; +import connectHistoryAPIFallback from 'connect-history-api-fallback'; + import { config } from './Config'; +// import { config } from './Config.js'; +import { webpackConfig } from './Build/WebpackConfig'; +// import { webpackConfig } from 'WebpackConfig'; +// import { webpackConfig } from './Build/WebpackConfig.js'; const debug = debug_base('app:server'); const app = express(); @@ -11,7 +16,7 @@ const paths = config.utils_paths; // This rewrites all routes requests to the root /index.html file (ignoring file requests). // If you want to implement universal rendering, you'll want to remove this middleware. -app.use(require('connect-history-api-fallback')({ +app.use(connectHistoryAPIFallback({ rewrites: [ { from: /^(.(?!\.(html|js|css|png|jpg)))+$/, // paths with these extensions will NOT be redirected to "index.html"" diff --git a/Scripts/package.json_disabled b/Scripts/package.json_disabled new file mode 100644 index 0000000..7dbc339 --- /dev/null +++ b/Scripts/package.json_disabled @@ -0,0 +1,4 @@ +{ + "@type": "Load the js files in this folder as es2015 modules, rather than commonjs.", + "type": "module" +} \ No newline at end of file diff --git a/Scripts/tsconfig.json b/Scripts/tsconfig.json index 624ae49..2610bb7 100644 --- a/Scripts/tsconfig.json +++ b/Scripts/tsconfig.json @@ -6,8 +6,8 @@ "forceConsistentCasingInFileNames": true, // creates duplicates in import-helper plugins otherwise // modules/paths - //"module": "ES2015", // leave the imports/exports alone (webpack will convert them to "require") - "module": "commonjs", // needed, since this config file is used for "ts-node Scripts/Server" as well + //"module": "ES2015", + "module": "commonjs", // needed, since ts-node does not yet support imports from es2015-modules "moduleResolution": "node", "rootDir": ".", "baseUrl": ".", @@ -18,17 +18,21 @@ // remove @types/react/global.d.ts, as it breaks the auto-import-finder for react-vcomponents/Text "react/global.d.ts": ["../Typings/empty.d.ts"], "react-vextensions/node_modules/react/global.d.ts": ["../Typings/empty.d.ts"], - "react-vcomponents/node_modules/react/global.d.ts": ["../Typings/empty.d.ts"], + "react-vcomponents/node_modules/react/global.d.ts": ["../Typings/empty.d.ts"] + //"WebpackConfig": ["./Build/WebpackConfig.ts"] }, + "resolveJsonModule": true, + // compiler options - "target": "esnext", + "target": "ES2015", + /*"target": "esnext", "lib": [ "es5", "es6", "ESNext", "dom" - ], + ],*/ "jsx": "react", "noImplicitAny": false, "alwaysStrict": true, // alternative: "@babel/plugin-transform-strict-mode"; went with this since doesn't require another npm package @@ -40,7 +44,7 @@ "include": [ "../Typings/**/*.d.ts", "../Scripts/**/*.ts", - "../Scripts/**/*.tsx" + "../Scripts/**/*.tsx", "Config.ts", "Build/WebpackConfig.ts" ], "compileOnSave": true } \ No newline at end of file diff --git a/package.json b/package.json index 6b6a079..f6b4278 100644 --- a/package.json +++ b/package.json @@ -10,18 +10,23 @@ "scripts": { "clean": "shx rm -rf Dist", "compile": "cross-env DEBUG='app:*' ts-node Scripts/Bin/Compile", - "lint": "eslint Source Tests Scripts", - "lint:fix": "npm run lint -- --fix", - "start": "cross-env DEBUG='app:*' ts-node Scripts/Server", + "@lint": "eslint Source Tests Scripts", + "@lint:fix": "npm run lint -- --fix", + "@start": "cross-env DEBUG='app:*' ts-node Scripts/Server", "@dev": "npm run create-config && nodemon Scripts/Server --watch Scripts --max_old_space_size=4096", "@@dev": "npm run create-config && ts-node-dev --project Scripts/tsconfig.json Scripts/Server", - "dev": "cross-env-shell NODE_ENV=development DEBUG='app:*' _USE_TSLOADER=true NODE_OPTIONS='--max-old-space-size=4096' \"npm run create-config && ts-node-dev --project Scripts/tsconfig.json Scripts/Server\"", - "dev-with-stats": "cross-env-shell NODE_ENV=development DEBUG='app:*' _USE_TSLOADER=true OUTPUT_STATS=true NODE_OPTIONS='--max-old-space-size=4096' \"npm run create-config && ts-node-dev --project Scripts/tsconfig.json Scripts/Server\"", + "@@@dev": "cross-env-shell NODE_ENV=development DEBUG='app:*' _USE_TSLOADER=true NODE_OPTIONS=\"--max-old-space-size=4096 --experimental-modules\" \"npm run create-config && npm run dev-part2\"", + "dev": "cross-env-shell NODE_ENV=development DEBUG='app:*' _USE_TSLOADER=true NODE_OPTIONS=\"--max-old-space-size=4096\" \"npm run create-config && npm run dev-part2\"", + "@dev-part2": "cross-env TS_NODE_OPTIONS=\"--experimental-modules\" ts-node-dev --project Scripts/tsconfig.json Scripts/Server.ts", + "@@dev-part2": "cross-env NODE_OPTIONS=\"--experimental-modules\" ts-node --project Scripts/tsconfig.json Scripts/Server.ts", + "dev-part2": "cross-env ts-node-dev --project Scripts/tsconfig.json Scripts/Server.ts", + "@dev-with-stats": "cross-env-shell NODE_ENV=development DEBUG='app:*' _USE_TSLOADER=true OUTPUT_STATS=true NODE_OPTIONS=\"--max-old-space-size=4096 --experimental-modules\" \"npm run create-config && ts-node-dev --project Scripts/tsconfig.json Scripts/Server\"", + "dev-with-stats": "cross-env-shell NODE_ENV=development DEBUG='app:*' _USE_TSLOADER=true OUTPUT_STATS=true NODE_OPTIONS=\"--max-old-space-size=4096\" \"npm run create-config && ts-node-dev --project Scripts/tsconfig.json Scripts/Server\"", "dev:no-debug": "npm run dev -- --no_debug", - "create-config": "cross-env DEBUG='app:*' ts-node Scripts/Build/CreateConfig", + "create-config": "cross-env DEBUG='app:*' NODE_OPTIONS=\"--experimental-modules\" ts-node Scripts/Build/CreateConfig.ts", "cypress:open": "cypress open", "cypress:run": "cypress run", - "build": "cross-env-shell DEBUG='app:*' 'npm run clean && npm run compile'", + "build": "cross-env-shell DEBUG='app:*' \"npm run clean && npm run compile\"", "build:dev": "cross-env NODE_ENV=development DEBUG='app:*' npm run build", "build:prod": "cross-env NODE_ENV=production DEBUG='app:*' npm run build", "build:prod-quick": "cross-env NODE_ENV=production DEBUG='app:*' QUICK=true npm run build",