Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions change/change-04d54498-920f-49a4-b451-0fa517df8b1e.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "major",
"comment": "Remove `enableTypeScript`, `tsconfig`, and `transpileOnly` options from `nodeExecTask` and `webpack*` tasks; remove `getTsNodeEnv` helper",
"packageName": "just-scripts",
"email": "email not defined",
"dependentChangeType": "patch"
}
]
}
11 changes: 11 additions & 0 deletions change/change-e41106ce-210a-4d8c-b5c5-cf9aaacb7105.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "major",
"comment": "Remove `ts-node` support and `--esm` CLI option; require Node.js 22.18+ native TypeScript type-stripping",
"packageName": "just-task",
"email": "email not defined",
"dependentChangeType": "patch"
}
]
}
6 changes: 3 additions & 3 deletions docs/tasks/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ task('sayhello', function () {

## Defining tasks in style with TypeScript

1. Install `ts-node` and `typescript`:
Node.js 22.18+ supports running TypeScript natively via [type stripping](https://nodejs.org/docs/latest-v22.x/api/typescript.html#type-stripping). Just takes advantage of this, so you only need `typescript` installed to make things work in your IDE:

```
npm i -D ts-node typescript
npm i -D typescript
```

2. Place tasks inside `just.config.ts` in your root folder (next to package.json):
Place tasks inside `just.config.ts` in your root folder (next to package.json):

```js
// ES Module style
Expand Down
2 changes: 1 addition & 1 deletion packages/just-example-lib/just.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { nodeExecTask, tscTask, task, parallel, watch } from 'just-scripts';
task('typescript', tscTask({}));
task('typescript:watch', tscTask({ watch: true }));

task('customNodeTask', nodeExecTask({ enableTypeScript: true, args: ['./tasks/customTask.ts'] }));
task('customNodeTask', nodeExecTask({ args: ['./tasks/customTask.ts'] }));

task('build', parallel('customNodeTask', 'typescript'));
task('watch', parallel('typescript:watch'));
Expand Down
3 changes: 1 addition & 2 deletions packages/just-example-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"node": ">=22.18.0"
},
"devDependencies": {
"just-scripts": "workspace:^",
"ts-node": "^10.8.0"
"just-scripts": "workspace:^"
}
}
2 changes: 1 addition & 1 deletion packages/just-example-lib/tasks/customTask.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import * as path from 'path';
import * as fs from 'fs';
export const packageJson = fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8');
export const packageJson = fs.readFileSync(path.join(import.meta.dirname, '../package.json'), 'utf-8');
8 changes: 0 additions & 8 deletions packages/just-scripts/etc/just-scripts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,8 @@ export function nodeExecTask(options: NodeExecTaskOptions): TaskFunction;
// @public (undocumented)
export interface NodeExecTaskOptions {
args: string[];
enableTypeScript?: boolean;
env?: NodeJS.ProcessEnv;
spawnOptions?: SpawnOptions;
transpileOnly?: boolean;
tsconfig?: string;
}

// @public (undocumented)
Expand Down Expand Up @@ -479,8 +476,6 @@ export function webpackCliTask(options?: WebpackCliTaskOptions): TaskFunction;
export interface WebpackCliTaskOptions {
env?: NodeJS.ProcessEnv;
nodeArgs?: string[];
transpileOnly?: boolean;
tsconfig?: string;
webpackCliArgs?: string[];
}

Expand All @@ -499,8 +494,6 @@ export interface WebpackDevServerTaskOptions extends WebpackCliTaskOptions, Conf
mode?: 'production' | 'development';
nodeArgs?: string[];
open?: boolean;
transpileOnly?: boolean;
tsconfig?: string;
}

export { webpackMerge }
Expand All @@ -527,7 +520,6 @@ export interface WebpackTaskOptions extends Configuration {
env?: NodeJS.ProcessEnv;
onCompile?: (err: Error, stats: any) => void | Promise<void>;
outputStats?: boolean | string;
transpileOnly?: boolean;
}


Expand Down
41 changes: 8 additions & 33 deletions packages/just-scripts/src/tasks/__tests__/nodeExecTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as path from 'path';
import { getMockScript } from '../../__tests__/getMockScript';
import { MockOutputStream } from '../../__tests__/MockOutputStream';
import * as execModule from '../../utils/exec';
import { nodeExecTask, type NodeExecTaskOptions } from '../nodeExecTask';
import { nodeExecTask } from '../nodeExecTask';
import { callTaskForTest } from './callTaskForTest';
import { getNormalizedSpawnArgs } from './getNormalizedSpawnArgs';

Expand Down Expand Up @@ -32,18 +32,8 @@ describe('nodeExecTask', () => {
jest.restoreAllMocks();
});

describe.each(['javascript', 'typescript (ts-node)'])('%s', fileType => {
const isTS = fileType !== 'javascript';
const ext = isTS ? 'ts' : 'js';
const maybeTsAutoArgs = isTS ? ['-r', '${repoRoot}/node_modules/ts-node/register/index.js'] : [];

/** Include appropriate TypeScript options with the task if needed */
function wrapNodeExecTask(options: NodeExecTaskOptions) {
return nodeExecTask({
...(isTS && { enableTypeScript: true, transpileOnly: true }),
...options,
});
}
describe.each(['javascript', 'typescript'])('%s', fileType => {
const ext = fileType !== 'javascript' ? 'ts' : 'js';

/** Wrap a test that should be successful with extra logging in case it fails */
async function wrapCallTask(task: TaskFunction, options?: { expectError?: boolean }) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this helper back to this location in the file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved wrapCallTask back inside the describe.each block. Commit: 7da8b82

Expand Down Expand Up @@ -71,17 +61,15 @@ describe('nodeExecTask', () => {
}
}

// These tests get expensive due to the IPC and especially with ts-node, so combine the basic
// success cases (args, default env)
// These tests get expensive due to the IPC, so combine the basic success cases (args, default env)
it('runs a script', async () => {
const task = wrapNodeExecTask({
const task = nodeExecTask({
args: ['--max-old-space-size=4096', getMockScript(`mock-success.${ext}`), '--', 'arg1', 'arg2'],
});
await wrapCallTask(task);

expect(getNormalizedSpawnArgs(spawnSpy)).toEqual([
'${nodeExecPath}',
...maybeTsAutoArgs,
'--max-old-space-size=4096',
`\${packageRoot}/src/__tests__/mock-success.${ext}`,
'--',
Expand All @@ -95,16 +83,10 @@ describe('nodeExecTask', () => {
// Just verify one value we expect to be present.
expect(process.env.JEST_WORKER_ID).toBeTruthy();
expect(output).toContain(`JEST_WORKER_ID=${process.env.JEST_WORKER_ID}`);

if (isTS) {
expect(output).toContain('TS_NODE_');
} else {
expect(output).not.toContain('TS_NODE_');
}
});

it('handles a script that fails', async () => {
const task = wrapNodeExecTask({
const task = nodeExecTask({
args: [getMockScript(`mock-fail.${ext}`)],
});
try {
Expand All @@ -118,7 +100,7 @@ describe('nodeExecTask', () => {
});

it('passes specified env only', async () => {
const task = wrapNodeExecTask({
const task = nodeExecTask({
args: [getMockScript(`mock-success.${ext}`)],
env: { FOO: 'foo value', BAR: 'bar value' },
});
Expand All @@ -131,18 +113,11 @@ describe('nodeExecTask', () => {
// verify a value we expect to be present in the current process isn't passed through
expect(process.env.JEST_WORKER_ID).toBeTruthy();
expect(output).not.toContain('JEST_WORKER_ID');

// In TS it would have failed if these were missed, but check anyway
if (isTS) {
expect(output).toContain('TS_NODE_');
} else {
expect(output).not.toContain('TS_NODE_');
}
});

it('errors if file not found', async () => {
const script = path.join(__dirname, `nope.${ext}`);
const task = wrapNodeExecTask({
const task = nodeExecTask({
args: [script],
});
try {
Expand Down
31 changes: 3 additions & 28 deletions packages/just-scripts/src/tasks/nodeExecTask.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { SpawnOptions } from 'child_process';
import { spawn } from '../utils';
import { logger, TaskFunction } from 'just-task';
import { resolveCwd, _tryResolve } from 'just-task/lib/resolve';
import { getTsNodeEnv } from '../typescript/getTsNodeEnv';

export interface NodeExecTaskOptions {
/**
Expand All @@ -20,21 +18,6 @@ export interface NodeExecTaskOptions {
*/
env?: NodeJS.ProcessEnv;

/**
* Whether to use `ts-node` to execute the script
*/
enableTypeScript?: boolean;

/**
* tsconfig file path to pass to `ts-node`
*/
tsconfig?: string;

/**
* Whether to use `transpileOnly` mode for `ts-node`
*/
transpileOnly?: boolean;

/**
* Custom spawn options.
*
Expand All @@ -53,23 +36,15 @@ export interface NodeExecTaskOptions {
*/
export function nodeExecTask(options: NodeExecTaskOptions): TaskFunction {
return function () {
const { spawnOptions, enableTypeScript, tsconfig, transpileOnly } = options;
const { spawnOptions } = options;

const tsNodeRegister = resolveCwd('ts-node/register');
const nodeExecPath = process.execPath;

const args = [...(options.args || [])];
// Preserve the default behavior of inheriting process.env if no options are specified
let env = options.env ? { ...options.env } : { ...process.env };
const isTS = enableTypeScript && tsNodeRegister;

if (isTS) {
args.unshift('-r', tsNodeRegister);

env = { ...env, ...getTsNodeEnv(tsconfig, transpileOnly) };
}
const env = options.env ? { ...options.env } : { ...process.env };

logger.info([`Executing${isTS ? ' [TS]' : ''}:`, nodeExecPath, ...args].join(' '));
logger.info(['Executing:', nodeExecPath, ...args].join(' '));

return spawn(nodeExecPath, args, { stdio: 'inherit', env, ...spawnOptions });
};
Expand Down
29 changes: 0 additions & 29 deletions packages/just-scripts/src/tasks/webpackCliTask.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { logger, TaskFunction, resolve } from 'just-task';
import { logNodeCommand, spawn } from '../utils';
import { getTsNodeEnv } from '../typescript/getTsNodeEnv';
import { findWebpackConfig } from '../webpack/findWebpackConfig';

export interface WebpackCliTaskOptions {
/**
Expand All @@ -19,16 +17,6 @@ export interface WebpackCliTaskOptions {
* Environment variables to be passed to the webpack-cli
*/
env?: NodeJS.ProcessEnv;

/**
* The tsconfig file to pass to ts-node for Typescript config
*/
tsconfig?: string;

/**
* Transpile the config only
*/
transpileOnly?: boolean;
}

/**
Expand All @@ -50,23 +38,6 @@ export function webpackCliTask(options: WebpackCliTaskOptions = {}): TaskFunctio
...(options && options.webpackCliArgs ? options.webpackCliArgs : []),
];

let configPath = findWebpackConfig('webpack.config.js');

if (configPath) {
options.env = {
...options.env,
...(configPath.endsWith('.ts') && getTsNodeEnv(options.tsconfig, options.transpileOnly)),
};
}

if (options.webpackCliArgs) {
const configIndex = options.webpackCliArgs.indexOf('--config');
const configPathAvailable = configIndex > -1 && options.webpackCliArgs.length > configIndex + 2;
if (configPathAvailable) {
configPath = options.webpackCliArgs[configIndex + 1];
}
}

logNodeCommand(args);

return spawn(process.execPath, args, { stdio: 'inherit', env: options.env });
Expand Down
15 changes: 0 additions & 15 deletions packages/just-scripts/src/tasks/webpackDevServerTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { resolve, resolveCwd, TaskFunction } from 'just-task';
import * as fs from 'fs';
import * as path from 'path';
import { WebpackCliTaskOptions } from './webpackCliTask';
import { getTsNodeEnv } from '../typescript/getTsNodeEnv';
import { findWebpackConfig } from '../webpack/findWebpackConfig';
import * as semver from 'semver';

Expand Down Expand Up @@ -35,16 +34,6 @@ export interface WebpackDevServerTaskOptions extends WebpackCliTaskOptions, Conf
* Environment variables to be passed to the spawned process of webpack-dev-server
*/
env?: { [key: string]: string | undefined };

/**
* The tsconfig file to pass to ts-node for Typescript config
*/
tsconfig?: string;

/**
* Transpile the config only
*/
transpileOnly?: boolean;
}

export function webpackDevServerTask(options: WebpackDevServerTaskOptions = {}): TaskFunction {
Expand Down Expand Up @@ -75,10 +64,6 @@ export function webpackDevServerTask(options: WebpackDevServerTaskOptions = {}):

if (configPath && fs.existsSync(configPath)) {
args = [...args, '--config', configPath];
options.env = {
...options.env,
...(configPath.endsWith('.ts') && getTsNodeEnv(options.tsconfig, options.transpileOnly)),
};
}

if (options.open) {
Expand Down
11 changes: 0 additions & 11 deletions packages/just-scripts/src/tasks/webpackTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as fs from 'fs';
import * as path from 'path';
import { merge } from 'webpack-merge';
import { findWebpackConfig } from '../webpack/findWebpackConfig';
import { enableTypeScript } from 'just-task/lib/enableTypeScript';

export interface WebpackTaskOptions extends Configuration {
config?: string;
Expand All @@ -19,11 +18,6 @@ export interface WebpackTaskOptions extends Configuration {
*/
env?: NodeJS.ProcessEnv;

/**
* Transpile the config only
*/
transpileOnly?: boolean;

/**
* Optional callback triggered on compile
*/
Expand All @@ -46,11 +40,6 @@ export function webpackTask(options?: WebpackTaskOptions): TaskFunction {

logger.info(`Webpack Config Path: ${webpackConfigPath}`);

if (webpackConfigPath && fs.existsSync(webpackConfigPath) && webpackConfigPath.endsWith('.ts')) {
const transpileOnly = options ? options.transpileOnly !== false : true;
enableTypeScript({ transpileOnly });
}

const configLoader = webpackConfigPath ? require(path.resolve(webpackConfigPath)) : {};

let webpackConfigs: Configuration[];
Expand Down
21 changes: 0 additions & 21 deletions packages/just-scripts/src/typescript/getTsNodeEnv.ts

This file was deleted.

Loading