From 383f04b96df3d61015dc5d3412e39dc6679e00e1 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Tue, 19 May 2020 11:08:29 +0200 Subject: [PATCH] feat(dev-infra): register ts-node when reading configuration (#37196) `ts-node` is now an optional peer dependency of the shared dev-infra package. Whenever a `ng-dev` command runs, and a TypeScript-based configuration file exists, `ts-node` is set up if available. That allows consumers of the package (as the components repo) to more conveniently use a TypeScript-based configuration for dev-infra. Currently, commands would need to be proxied through `ts-node` which rather complicates the setup: ``` NG_DEV_COMMAND="ts-node ./node_modules/@angular/dev-infra-private/cli.js" ``` I'm thinking that it should be best-practice to use TypeScript for writing the configuration files. Given that the tool is used primarily in Angular projects (for which most sources are TypeScript), this should be acceptable. PR Close #37196 --- dev-infra/tmpl-package.json | 6 ++++++ dev-infra/utils/config.ts | 31 +++++++++++++++++++++++++------ dev-infra/utils/ts-node.ts | 17 +++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 dev-infra/utils/ts-node.ts diff --git a/dev-infra/tmpl-package.json b/dev-infra/tmpl-package.json index e1ffd09573..5903d5f223 100644 --- a/dev-infra/tmpl-package.json +++ b/dev-infra/tmpl-package.json @@ -24,7 +24,13 @@ "peerDependencies": { "@bazel/buildifier": "", "clang-format": "", + "ts-node": "", "tslib": "", "typescript": "" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } } } diff --git a/dev-infra/utils/config.ts b/dev-infra/utils/config.ts index 260c5a7930..3c73301640 100644 --- a/dev-infra/utils/config.ts +++ b/dev-infra/utils/config.ts @@ -6,8 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ +import {existsSync} from 'fs'; import {join} from 'path'; import {exec} from 'shelljs'; +import {isTsNodeAvailable} from './ts-node'; /** * Describes the Github configuration for dev-infra. This configuration is @@ -41,17 +43,16 @@ const CONFIG_FILE_NAME = '.ng-dev-config'; let CONFIG: {}|null = null; /** - * Get the configuration from the file system, returning the already loaded copy if it - * is defined. + * Get the configuration from the file system, returning the already loaded + * copy if it is defined. */ export function getConfig(): NgDevConfig { // If the global config is not defined, load it from the file system. if (CONFIG === null) { // The full path to the configuration file. const configPath = join(getRepoBaseDir(), CONFIG_FILE_NAME); - // Set the global config object to a clone of the configuration loaded through default exports - // from the config file. - CONFIG = {...require(configPath)}; + // Set the global config object. + CONFIG = readConfigFile(configPath); } // Return a clone of the global config to ensure that a new instance of the config is returned // each time, preventing unexpected effects of modifications to the config object. @@ -72,10 +73,28 @@ function validateCommonConfig(config: Partial) { errors.push(`"github.owner" is not defined`); } } - + assertNoErrors(errors); return config as NgDevConfig; } +/** Resolves and reads the specified configuration file. */ +function readConfigFile(configPath: string): object { + // If the the `.ts` extension has not been set up already, and a TypeScript based + // version of the given configuration seems to exist, set up `ts-node` if available. + if (require.extensions['.ts'] === undefined && existsSync(`${configPath}.ts`) && + isTsNodeAvailable()) { + require('ts-node').register({skipProject: true, transpileOnly: true}); + } + + try { + return require(configPath) + } catch (e) { + console.error('Could not read configuration file.'); + console.error(e); + process.exit(1); + } +} + /** * Asserts the provided array of error messages is empty. If any errors are in the array, * logs the errors and exit the process as a failure. diff --git a/dev-infra/utils/ts-node.ts b/dev-infra/utils/ts-node.ts new file mode 100644 index 0000000000..b21518ccfb --- /dev/null +++ b/dev-infra/utils/ts-node.ts @@ -0,0 +1,17 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/** Whether ts-node has been installed and is available to ng-dev. */ +export function isTsNodeAvailable(): boolean { + try { + require.resolve('ts-node'); + return true; + } catch { + return false; + } +}