diff --git a/change/just-scripts-2020-10-09-13-31-44-node-exec.json b/change/just-scripts-2020-10-09-13-31-44-node-exec.json new file mode 100644 index 00000000..4d6d16a2 --- /dev/null +++ b/change/just-scripts-2020-10-09-13-31-44-node-exec.json @@ -0,0 +1,8 @@ +{ + "type": "minor", + "comment": "adds a new nodeExecTask that optionally supports ts-node", + "packageName": "just-scripts", + "email": "kchau@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-10-09T20:31:44.680Z" +} diff --git a/packages/example-lib/just-task.js b/packages/example-lib/just-task.js deleted file mode 100644 index d81fa173..00000000 --- a/packages/example-lib/just-task.js +++ /dev/null @@ -1,7 +0,0 @@ -const { tscTask, task, parallel } = require('just-scripts'); - -task('typescript', tscTask({})); -task('typescript:watch', tscTask({ watch: true })); - -task('build', parallel('typescript')); -task('watch', parallel('typescript:watch')); diff --git a/packages/example-lib/just.config.ts b/packages/example-lib/just.config.ts new file mode 100644 index 00000000..195115cb --- /dev/null +++ b/packages/example-lib/just.config.ts @@ -0,0 +1,9 @@ +import { nodeExecTask, tscTask, task, parallel } from 'just-scripts'; + +task('typescript', tscTask({})); +task('typescript:watch', tscTask({ watch: true })); + +task('customNodeTask', nodeExecTask({ enableTypeScript: true, args: ['./tasks/customTask.ts'] })); + +task('build', parallel('customNodeTask', 'typescript')); +task('watch', parallel('typescript:watch')); diff --git a/packages/example-lib/package.json b/packages/example-lib/package.json index c4f12e59..a65aa582 100644 --- a/packages/example-lib/package.json +++ b/packages/example-lib/package.json @@ -12,6 +12,7 @@ "license": "MIT", "devDependencies": { "just-scripts": ">=1.1.0 <2.0.0", + "ts-node": "^9.0.0", "typescript": "^4.0.3" } } diff --git a/packages/example-lib/tasks/customTask.ts b/packages/example-lib/tasks/customTask.ts new file mode 100644 index 00000000..9724df52 --- /dev/null +++ b/packages/example-lib/tasks/customTask.ts @@ -0,0 +1,3 @@ +import * as path from 'path'; +import * as fs from 'fs'; +export const packageJson = fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'); diff --git a/packages/just-scripts/src/tasks/index.ts b/packages/just-scripts/src/tasks/index.ts index 8a36c475..49975168 100644 --- a/packages/just-scripts/src/tasks/index.ts +++ b/packages/just-scripts/src/tasks/index.ts @@ -13,3 +13,4 @@ export * from './webpackCliInitTask'; export * from './webpackCliTask'; export * from './webpackDevServerTask'; export * from './tarTask'; +export * from './nodeExecTask'; diff --git a/packages/just-scripts/src/tasks/nodeExecTask.ts b/packages/just-scripts/src/tasks/nodeExecTask.ts new file mode 100644 index 00000000..26eb6c71 --- /dev/null +++ b/packages/just-scripts/src/tasks/nodeExecTask.ts @@ -0,0 +1,59 @@ +import { spawn, SpawnOptions } from 'child_process'; +import { logger } from 'just-task'; +import { resolveCwd, _tryResolve } from 'just-task/lib/resolve'; +import { getTsNodeEnv } from '../typescript/getTsNodeEnv'; + +export interface NodeExecTaskOptions { + /** + * Arguments to be passed into a spawn call for webpack dev server. This can be used to do things + * like increase the heap space for the JS engine to address out of memory issues. + */ + args?: string[]; + + /** + * Environment variables to be passed to the webpack-cli + */ + env?: NodeJS.ProcessEnv; + + /** + * Should this nodeExec task be using something like ts-node to execute the binary + */ + enableTypeScript?: boolean; + + /** + * The tsconfig file to pass to ts-node for Typescript config + */ + tsconfig?: string; + + /** + * Transpile the config only + */ + transpileOnly?: boolean; + + /** + * Custom spawn options + */ + spawnOptions?: SpawnOptions; +} + +export function nodeExecTask(options: NodeExecTaskOptions) { + return function () { + const { spawnOptions, enableTypeScript, tsconfig, transpileOnly } = options; + + const tsNodeRegister = resolveCwd('ts-node/register'); + const nodeExecPath = process.execPath; + + if (enableTypeScript && tsNodeRegister) { + options.args = options.args || []; + options.args.unshift(tsNodeRegister); + options.args.unshift('-r'); + + options.env = { ...options.env, ...getTsNodeEnv(tsconfig, transpileOnly) }; + logger.info('Executing [TS]: ' + [nodeExecPath, ...(options.args || [])].join(' ')); + } else { + logger.info('Executing: ' + [nodeExecPath, ...(options.args || [])].join(' ')); + } + + return spawn(nodeExecPath, options.args, { stdio: 'inherit', env: options.env, ...spawnOptions }); + }; +} diff --git a/packages/just-scripts/src/tasks/webpackCliTask.ts b/packages/just-scripts/src/tasks/webpackCliTask.ts index ec1a1cb3..2197ab2f 100644 --- a/packages/just-scripts/src/tasks/webpackCliTask.ts +++ b/packages/just-scripts/src/tasks/webpackCliTask.ts @@ -1,6 +1,6 @@ import { logger, TaskFunction, resolve } from 'just-task'; import { spawn } from 'just-scripts-utils'; -import { getTsNodeWebpackEnv } from '../webpack/getTsNodeWebpackEnv'; +import { getTsNodeEnv } from '../typescript/getTsNodeEnv'; import { findWebpackConfig } from '../webpack/findWebpackConfig'; export interface WebpackCliTaskOptions { @@ -66,7 +66,7 @@ export function webpackCliTask(options: WebpackCliTaskOptions = {}): TaskFunctio logger.info(`webpack-cli arguments: ${process.execPath} ${args.join(' ')}`); - options.env = { ...options.env, ...getTsNodeWebpackEnv(configPath, options.tsconfig, options.transpileOnly) }; + options.env = { ...options.env, ...(configPath.endsWith('.ts') && getTsNodeEnv(options.tsconfig, options.transpileOnly)) }; return spawn(process.execPath, args, { stdio: 'inherit', env: options.env }); }; diff --git a/packages/just-scripts/src/tasks/webpackDevServerTask.ts b/packages/just-scripts/src/tasks/webpackDevServerTask.ts index 51f8c65c..2845e761 100644 --- a/packages/just-scripts/src/tasks/webpackDevServerTask.ts +++ b/packages/just-scripts/src/tasks/webpackDevServerTask.ts @@ -4,7 +4,7 @@ import { encodeArgs, spawn } from 'just-scripts-utils'; import { logger, resolve } from 'just-task'; import * as fs from 'fs'; import { WebpackCliTaskOptions } from './webpackCliTask'; -import { getTsNodeWebpackEnv } from '../webpack/getTsNodeWebpackEnv'; +import { getTsNodeEnv } from '../typescript/getTsNodeEnv'; import { findWebpackConfig } from '../webpack/findWebpackConfig'; export interface WebpackDevServerTaskOptions extends WebpackCliTaskOptions, Configuration { @@ -63,7 +63,7 @@ export function webpackDevServerTask(options: WebpackDevServerTaskOptions = {}) args = [...args, ...options.webpackCliArgs]; } - options.env = { ...options.env, ...getTsNodeWebpackEnv(configPath, options.tsconfig, options.transpileOnly) }; + options.env = { ...options.env, ...(configPath.endsWith('.ts') && getTsNodeEnv(options.tsconfig, options.transpileOnly)) }; logger.info(process.execPath, encodeArgs(args).join(' ')); return spawn(process.execPath, args, { stdio: 'inherit', env: options.env }); diff --git a/packages/just-scripts/src/typescript/getTsNodeEnv.ts b/packages/just-scripts/src/typescript/getTsNodeEnv.ts new file mode 100644 index 00000000..843c2e34 --- /dev/null +++ b/packages/just-scripts/src/typescript/getTsNodeEnv.ts @@ -0,0 +1,21 @@ +import { logger } from 'just-task'; + +export function getTsNodeEnv(tsconfig?: string, transpileOnly?: boolean) { + const env: { [key: string]: string | undefined } = {}; + + if (tsconfig) { + logger.info(`[TS] Using ${tsconfig}`); + env.TS_NODE_PROJECT = tsconfig; + } else { + const compilerOptions = JSON.stringify({ module: 'commonjs', target: 'es2017', moduleResolution: 'node' }); + logger.info(`[TS] Using these compilerOptions: ${compilerOptions}`); + env.TS_NODE_COMPILER_OPTIONS = compilerOptions; + } + + if (transpileOnly !== false) { + logger.info('[TS] Using transpileOnly mode'); + env.TS_NODE_TRANSPILE_ONLY = 'true'; + } + + return env; +} diff --git a/packages/just-scripts/src/webpack/getTsNodeWebpackEnv.ts b/packages/just-scripts/src/webpack/getTsNodeWebpackEnv.ts deleted file mode 100644 index f488379e..00000000 --- a/packages/just-scripts/src/webpack/getTsNodeWebpackEnv.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function getTsNodeWebpackEnv(configPath: string, tsconfig?: string, transpileOnly?: boolean) { - const env: { [key: string]: string | undefined } = {}; - - if (tsconfig) { - env.TS_NODE_PROJECT = tsconfig; - } else { - env.TS_NODE_COMPILER_OPTIONS = JSON.stringify({ module: 'commonjs', target: 'es2017', moduleResolution: 'node' }); - } - - if (configPath.endsWith('.ts') && transpileOnly !== false) { - env.TS_NODE_TRANSPILE_ONLY = 'true'; - } - - return env; -} diff --git a/yarn.lock b/yarn.lock index f1ba83f4..cfb9d808 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1985,6 +1985,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -3776,6 +3781,11 @@ diff-sequences@^24.9.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" @@ -7458,6 +7468,11 @@ make-error@1.x: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -10058,6 +10073,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.5.17: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@^0.5.6, source-map-support@^0.5.9: version "0.5.12" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" @@ -10732,6 +10755,17 @@ ts-jest@^24.0.1: semver "^5.5" yargs-parser "10.x" +ts-node@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3" + integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + tslib@^1.10.0: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" @@ -11410,6 +11444,11 @@ yauzl@^2.4.2: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + z-schema@~3.18.3: version "3.18.4" resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.18.4.tgz#ea8132b279533ee60be2485a02f7e3e42541a9a2"