Feat/427: Serve explicit environments (#433)

* feat: add env specific serve commands where appropriate for apps

* fix: typo in command call

* feat: add custom executor for serving apps

* chore: clean up project files and use the custom executor

* chore: patch readmes

* chore: split out logs into their own function

* fix: prevent overriding env when no flag passed in

* fix: add tsc to postinstall to take care of compiling the custom executors

* fix: remove the custom serve executor from trading
This commit is contained in:
botond 2022-05-23 10:56:11 +01:00 committed by GitHub
parent 66c8d195a2
commit a6a21bed46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 267 additions and 12 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
/dist
/tmp
/out-tsc
/tools/executors/**/*.js
# dependencies
/node_modules

View File

@ -32,12 +32,18 @@ yarn nx serve explorer
Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Testnet](./.env.testnet)
- [Devnet](./.env.devnet)
- [Capsule](./.env.capsule)
- [Testnet](./.env.testnet)
- [Stagnet1](./.env.stagnet1)
- [Stagnet2](./.env.stagnet2)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn nx run explorer:serve --env={env} # e.g. stagnet1
```
There are a few different configuration options offered for this app:
| **Flag** | **Purpose** |

View File

@ -38,7 +38,7 @@
}
},
"serve": {
"executor": "@nrwl/web:dev-server",
"executor": "./tools/executors/serve:serve",
"options": {
"port": 3000,
"buildTarget": "explorer:build",

View File

@ -41,7 +41,7 @@
}
},
"serve": {
"executor": "@nrwl/web:dev-server",
"executor": "./tools/executors/serve:serve",
"options": {
"buildTarget": "simple-trading-app:build",
"hmr": true,

View File

@ -36,7 +36,7 @@
}
},
"serve": {
"executor": "@nrwl/web:dev-server",
"executor": "./tools/executors/serve:serve",
"options": {
"buildTarget": "static:build"
},

View File

@ -37,7 +37,7 @@
}
},
"serve": {
"executor": "@nrwl/web:dev-server",
"executor": "./tools/executors/serve:serve",
"options": {
"port": 3010,
"buildTarget": "stats:build",

View File

@ -16,10 +16,26 @@
Starting the app:
`yarn nx serve token`
```bash
yarn nx serve token
```
## Configuration
Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Devnet](./.env.devnet)
- [Testnet](./.env.testnet)
- [Stagnet1](./.env.stagnet1)
- [Stagnet2](./.env.stagnet2)
For convenience, you can boot the app injecting one of the configurations above by running:
```bash
yarn nx run token:serve --env={env} # e.g. stagnet1
```
There are a few different configuration options offered for this app:
| **Flag** | **Purpose** |

View File

@ -38,7 +38,7 @@
}
},
"serve": {
"executor": "@nrwl/web:dev-server",
"executor": "./tools/executors/serve:serve",
"options": {
"port": 4210,
"buildTarget": "token:build",

View File

@ -19,7 +19,7 @@ yarn nx serve explorer
Example configurations are provided here:
- [Mainnet](./.env.mainnet)
- [Testnet](./.env.testnet)
- [Devnet](./.env.devnet)
- [Testnet](./.env.testnet)
- [Stagnet1](./.env.stagnet1)
- [Stagnet2](./.env.stagnet2)

View File

@ -6,7 +6,7 @@
"start": "nx serve",
"build": "nx build",
"test": "nx test",
"postinstall": "husky install"
"postinstall": "husky install && yarn tsc -b tools/executors/**"
},
"engines": {
"node": ">=16.14.0"
@ -122,6 +122,7 @@
"babel-loader": "8.1.0",
"cypress": "^9.5.4",
"cypress-cucumber-preprocessor": "^4.3.1",
"dotenv": "^16.0.1",
"eslint": "8.12.0",
"eslint-config-next": "12.1.2",
"eslint-config-prettier": "8.1.0",
@ -138,6 +139,7 @@
"jest-canvas-mock": "^2.3.1",
"jest-websocket-mock": "^2.3.0",
"lint-staged": "^12.3.3",
"npmlog": "^6.0.2",
"nx": "13.10.1",
"prettier": "^2.5.1",
"react-test-renderer": "17.0.2",

View File

@ -0,0 +1,9 @@
{
"executors": {
"serve": {
"implementation": "./impl",
"schema": "./schema.json",
"description": "Starts a dev-server with an optional explicit environment."
}
}
}

View File

@ -0,0 +1,89 @@
import * as fs from 'fs';
import * as path from 'path';
import * as dotenv from 'dotenv';
import * as log from 'npmlog';
import type { ExecutorContext } from '@nrwl/devkit';
import devServerExecutor, {
WebDevServerOptions,
} from '@nrwl/web/src/executors/dev-server/dev-server.impl';
type Schema = WebDevServerOptions & {
env?: string;
};
const LOGGER_SCOPE = 'tools/executors/serve';
const logEnvData = (
envMap: Record<string, string>,
envFiles: string[],
env?: string,
defaultEnvFile?: string
) => {
if (env && !envMap[env]) {
log.warn(LOGGER_SCOPE, `No environment called "${env}" found.`);
log.info(
LOGGER_SCOPE,
envFiles.length > 0
? `You can create a new environment by putting an ".env.${env}" file in your project root, or you can use the following available ones: ${envFiles.join(
', '
)}.`
: 'To get started with environments, you can create an ".env" file in your project root with the desired variables.'
);
}
if (!envMap[env]) {
log.info(
LOGGER_SCOPE,
defaultEnvFile
? `Using "${defaultEnvFile}" as the default project environment.`
: 'Serving the project only using the environment variables scoped to your CLI.'
);
} else {
log.info(
LOGGER_SCOPE,
`Using "${envMap[env]}" as the default project environment.`
);
}
};
const filenameToEnv = (filename: string) => filename.replace('.env.', '');
const getDefaultEnvFile = (envMap: Record<string, string>) => {
return envMap['local'] || envMap['.env'];
};
const getEnvFile = (env: string, envFiles: string[]) => {
const envMap = envFiles.reduce(
(acc, filename) => ({
...acc,
[filenameToEnv(filename)]: filename,
}),
{}
);
const defaultEnvFile = getDefaultEnvFile(envMap);
logEnvData(envMap, envFiles, env, defaultEnvFile);
return envMap[env] || defaultEnvFile;
};
export default async function* serve(
options: Schema,
context: ExecutorContext
): ReturnType<typeof devServerExecutor> {
const { env, ...dsOptions } = options;
const { root } = context.workspace.projects[context.projectName];
const workspacePath = path.join(context.cwd, root);
const files = await fs.promises.readdir(workspacePath);
const envFile = getEnvFile(
env,
files.filter((f) => f.startsWith('.env'))
);
if (env && envFile) {
dotenv.config({ path: path.join(workspacePath, envFile), override: true });
}
return yield* devServerExecutor(dsOptions, context);
}

View File

@ -0,0 +1,3 @@
{
"executors": "./executor.json"
}

View File

@ -0,0 +1,79 @@
{
"cli": "nx",
"id": "serve",
"description": "Serves an app using @nrwl/web:dev-server",
"type": "object",
"properties": {
"env": {
"type": "string",
"description": "Target environment to run the application in. This assumes an .env file present in the project's root in the following format: .env.{envName}"
},
"buildTarget": {
"type": "string",
"description": "Target which builds the application."
},
"port": {
"type": "number",
"description": "Port to listen on.",
"default": 4200
},
"host": {
"type": "string",
"description": "Host to listen on.",
"default": "localhost"
},
"ssl": {
"type": "boolean",
"description": "Serve using `HTTPS`.",
"default": false
},
"sslKey": {
"type": "string",
"description": "SSL key to use for serving `HTTPS`."
},
"sslCert": {
"type": "string",
"description": "SSL certificate to use for serving `HTTPS`."
},
"watch": {
"type": "boolean",
"description": "Watches for changes and rebuilds application.",
"default": true
},
"liveReload": {
"type": "boolean",
"description": "Whether to reload the page on change, using live-reload.",
"default": true
},
"hmr": {
"type": "boolean",
"description": "Enable hot module replacement.",
"default": false
},
"publicHost": {
"type": "string",
"description": "Public URL where the application will be served."
},
"open": {
"type": "boolean",
"description": "Open the application in the browser.",
"default": false
},
"allowedHosts": {
"type": "string",
"description": "This option allows you to whitelist services that are allowed to access the dev server."
},
"memoryLimit": {
"type": "number",
"description": "Memory limit for type checking service process in `MB`."
},
"maxWorkers": {
"type": "number",
"description": "Number of workers to use for type checking."
},
"baseHref": {
"type": "string",
"description": "Base url for the application being built."
}
}
}

View File

@ -0,0 +1,13 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"types": ["node"],
"importHelpers": false,
"sourceMap": false,
"inlineSourceMap": true
},
"include": ["impl.ts"],
"exclude": ["node_modules"]
}

View File

@ -7340,6 +7340,14 @@ are-we-there-yet@^2.0.0:
delegates "^1.0.0"
readable-stream "^3.6.0"
are-we-there-yet@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d"
integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==
dependencies:
delegates "^1.0.0"
readable-stream "^3.6.0"
are-we-there-yet@~1.1.2:
version "1.1.7"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
@ -9206,7 +9214,7 @@ color-name@^1.1.4, color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-support@^1.1.2:
color-support@^1.1.2, color-support@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
@ -10670,6 +10678,11 @@ dotenv-expand@^5.1.0:
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
dotenv@^16.0.1:
version "16.0.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d"
integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==
dotenv@^8.0.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
@ -12290,6 +12303,20 @@ gauge@^3.0.0:
strip-ansi "^6.0.1"
wide-align "^1.1.2"
gauge@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce"
integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==
dependencies:
aproba "^1.0.3 || ^2.0.0"
color-support "^1.1.3"
console-control-strings "^1.1.0"
has-unicode "^2.0.1"
signal-exit "^3.0.7"
string-width "^4.2.3"
strip-ansi "^6.0.1"
wide-align "^1.1.5"
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@ -16237,6 +16264,16 @@ npmlog@^5.0.1:
gauge "^3.0.0"
set-blocking "^2.0.0"
npmlog@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830"
integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==
dependencies:
are-we-there-yet "^3.0.0"
console-control-strings "^1.1.0"
gauge "^4.0.3"
set-blocking "^2.0.0"
nth-check@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
@ -19314,7 +19351,7 @@ side-channel@^1.0.4:
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
@ -21826,7 +21863,7 @@ which@^2.0.1, which@^2.0.2:
dependencies:
isexe "^2.0.0"
wide-align@^1.1.0, wide-align@^1.1.2:
wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==