Skip to content
Open
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
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ temp
LICENSE
CHANGELOG.*
SECURITY.md
*.api.md
11 changes: 11 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@
"sourceMaps": true,
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"name": "Debug example-lib build",
"request": "launch",
"type": "node",
"runtimeExecutable": "yarn",
"runtimeArgs": ["run", "build"],
"cwd": "${workspaceFolder}/packages/example-lib",
"console": "integratedTerminal",
"outputCapture": "std",
"sourceMaps": true
}
]
}
11 changes: 11 additions & 0 deletions change/change-0c7dafd4-b632-47f2-bacf-b22077ce3c51.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "minor",
"comment": "`nodeExecTask`: add `enableTypeScript: esm` setting to run the task in `ts-node` with ESM support",
"packageName": "just-scripts",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
]
}
11 changes: 11 additions & 0 deletions change/change-3e7ef03c-6140-4b48-b824-f7303ca53d62.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "patch",
"comment": "Detect if already running in ts-node or tsx and skip call to ts-node register",
"packageName": "just-task",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
]
}
11 changes: 11 additions & 0 deletions change/change-48ef8505-5b31-4b60-bfe2-53e1433985cd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "minor",
"comment": "Compile just with TS 4.7 and `module`/`moduleResolution` `\"Node16\"`",
"packageName": "just-scripts",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
]
}
11 changes: 11 additions & 0 deletions change/change-9ea30187-bf7e-4cd9-ba0a-e1af7e7b3bdc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "minor",
"comment": "For ts-node, use `module`/`moduleResolution` `\"Node16\"` if the local TS version supports it",
"packageName": "just-task",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
]
}
11 changes: 11 additions & 0 deletions change/change-9eb2d5fb-3a3f-4714-8fd7-5bac2166d20d.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "minor",
"comment": "Partial support for ESM packages: load `just.config.js` as ESM if package has `type: \"module\"`, and support explicit `.cjs`, `.mjs`, and `.cts` extensions. (`.ts` configs in packages with `type: \"module\"` are not supported due to limitations with `ts-node` `register()`.)",
"packageName": "just-task",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
]
}
11 changes: 11 additions & 0 deletions change/change-e400c7a0-47ba-4cf5-b712-508ad7481673.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "minor",
"comment": "Compile just with TS 4.7 and `module`/`moduleResolution` `\"Node16\"`",
"packageName": "just-task",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
]
}
14 changes: 13 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"prettier": "^2.8.4",
"syncpack": "^9.0.0",
"ts-jest": "^29.0.5",
"typescript": "~4.3.5",
"typescript": "~4.7.0",
"vuepress": "^1.9.9",
"vuepress-plugin-mermaidjs": "^1.9.1",
"workspace-tools": "^0.35.2"
Expand All @@ -74,6 +74,18 @@
"dependencyTypes": [
"dev",
"prod"
],
"versionGroups": [
{
"label": "ts-node (testing with multiple versions)",
"dependencies": [
"ts-node"
],
"packages": [
"**"
],
"isIgnored": true
}
]
},
"workspaces": {
Expand Down
3 changes: 3 additions & 0 deletions packages/example-lib-esm-ts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This package has `"type": "module"` in its `package.json`. If the just config was `just.config.ts`, this would be implicitly considered as ESM, and loading TS files as ESM isn't supported with `ts-node` `register()` (it must be configured with a `--loader` option when the Node process is created). So the package has to use `just.config.cts` instead.

The just config also defines a `nodeExecTask` which must be handled as ESM. The custom task file can be a normal `.ts` which is treated as ESM because `enableTypeScript: 'esm'` is set, and the task is run in a separate Node process where the `--loader` can be used.
14 changes: 14 additions & 0 deletions packages/example-lib-esm-ts/just.config.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { nodeExecTask, tscTask, task, parallel } from 'just-scripts';

task('typescript', tscTask({}));

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

task('build', parallel('customNodeTask', 'typescript'));
14 changes: 14 additions & 0 deletions packages/example-lib-esm-ts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "example-lib-esm-ts",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "just-scripts build"
},
"license": "MIT",
"devDependencies": {
"just-scripts": ">=2.2.3 <3.0.0",
"ts-node": "^10.0.0"
}
}
1 change: 1 addition & 0 deletions packages/example-lib-esm-ts/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const a = 5;
7 changes: 7 additions & 0 deletions packages/example-lib-esm-ts/tasks/customTask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as path from 'path';
import * as fs from 'fs';
import { fileURLToPath } from 'url';

const dirname = path.dirname(fileURLToPath(import.meta.url));

export const packageJson = fs.readFileSync(path.resolve(dirname, '../package.json'), 'utf-8');
15 changes: 15 additions & 0 deletions packages/example-lib-esm-ts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
"declarationMap": true,
"outDir": "lib",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": []
},
"include": ["src"]
}
1 change: 1 addition & 0 deletions packages/example-lib-esm-tsnode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This package has `"type": "module"` in its `package.json`. The config is a `.ts` which will be treated as ESM, and Just can't handle that directly (see [`example-lib-esm-ts` readme](../example-lib-esm-ts/README.md)). So the package's `"build"` script wraps the `just-scripts` binary with the transpiler: `ts-node-esm node_modules/.bin/just-scripts build`.
14 changes: 14 additions & 0 deletions packages/example-lib-esm-tsnode/just.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { nodeExecTask, tscTask, task, parallel } from 'just-scripts';

task('typescript', tscTask({}));

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

task('build', parallel('customNodeTask', 'typescript'));
14 changes: 14 additions & 0 deletions packages/example-lib-esm-tsnode/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "example-lib-esm-tsnode",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "ts-node-esm node_modules/.bin/just-scripts build"
},
"license": "MIT",
"devDependencies": {
"just-scripts": ">=2.2.3 <3.0.0",
"ts-node": "^10.0.0"
}
}
1 change: 1 addition & 0 deletions packages/example-lib-esm-tsnode/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const a = 5;
7 changes: 7 additions & 0 deletions packages/example-lib-esm-tsnode/tasks/customTask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as path from 'path';
import * as fs from 'fs';
import { fileURLToPath } from 'url';

const dirname = path.dirname(fileURLToPath(import.meta.url));

export const packageJson = fs.readFileSync(path.resolve(dirname, '../package.json'), 'utf-8');
15 changes: 15 additions & 0 deletions packages/example-lib-esm-tsnode/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
"declarationMap": true,
"outDir": "lib",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": []
},
"include": ["src"]
}
3 changes: 3 additions & 0 deletions packages/example-lib-esm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This package has `"type": "module"` in its `package.json`, so its `just.config.js` must be loaded as ESM.

The just config also defines a `nodeExecTask` which must be handled as ESM.
7 changes: 7 additions & 0 deletions packages/example-lib-esm/just.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { nodeExecTask, tscTask, task, parallel } from 'just-scripts';

task('typescript', tscTask({}));

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

task('build', parallel('customNodeTask', 'typescript'));
14 changes: 14 additions & 0 deletions packages/example-lib-esm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "example-lib-esm",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "just-scripts build"
},
"license": "MIT",
"devDependencies": {
"just-scripts": ">=2.2.3 <3.0.0",
"ts-node": "^9.1.1"
}
}
1 change: 1 addition & 0 deletions packages/example-lib-esm/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const a = 5;
7 changes: 7 additions & 0 deletions packages/example-lib-esm/tasks/customTask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as path from 'path';
import * as fs from 'fs';
import { fileURLToPath } from 'url';

const dirname = path.dirname(fileURLToPath(import.meta.url));

export const packageJson = fs.readFileSync(path.resolve(dirname, '../package.json'), 'utf-8');
15 changes: 15 additions & 0 deletions packages/example-lib-esm/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
"declarationMap": true,
"outDir": "lib",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": []
},
"include": ["src"]
}
9 changes: 8 additions & 1 deletion packages/example-lib/just.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ 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({
enableTypeScript: true,
transpileOnly: true,
args: ['./tasks/customTask.ts'],
}),
);

task('build', parallel('customNodeTask', 'typescript'));
task('watch', parallel('typescript:watch'));
Expand Down
7 changes: 0 additions & 7 deletions packages/example-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@
"name": "example-lib",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "just-scripts build"
},
"keywords": [],
"author": "",
"license": "MIT",
"engines": {
"node": ">=14"
},
"devDependencies": {
"just-scripts": ">=2.2.3 <3.0.0",
"ts-node": "^9.1.1"
Expand Down
4 changes: 2 additions & 2 deletions packages/just-scripts/etc/just-scripts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ export function nodeExecTask(options: NodeExecTaskOptions): TaskFunction;
// @public (undocumented)
export interface NodeExecTaskOptions {
args?: string[];
enableTypeScript?: boolean;
enableTypeScript?: boolean | 'esm';
env?: NodeJS.ProcessEnv;
spawnOptions?: SpawnOptions;
transpileOnly?: boolean;
Expand Down Expand Up @@ -445,7 +445,7 @@ export interface TsLoaderOptions {
}

// @public (undocumented)
export const tsOverlay: (overlayOptions?: TsOverlayOptions | undefined) => Partial<Configuration>;
export const tsOverlay: (overlayOptions?: TsOverlayOptions) => Partial<Configuration>;

// @public (undocumented)
export interface TsOverlayOptions {
Expand Down
24 changes: 13 additions & 11 deletions packages/just-scripts/src/tasks/nodeExecTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ export interface NodeExecTaskOptions {
env?: NodeJS.ProcessEnv;

/**
* Should this nodeExec task be using something like ts-node to execute the binary
* Whether this nodeExec task should use ts-node to execute the binary.
* If set to `esm`, it will use `ts-node/esm` instead of `ts-node/register`.
*/
enableTypeScript?: boolean;
enableTypeScript?: boolean | 'esm';

/**
* The tsconfig file to pass to ts-node for Typescript config
Expand All @@ -40,21 +41,22 @@ export interface NodeExecTaskOptions {
export function nodeExecTask(options: NodeExecTaskOptions): TaskFunction {
return function () {
const { spawnOptions, enableTypeScript, tsconfig, transpileOnly } = options;
const args = [...(options.args || [])];
const env = { ...options.env };

const tsNodeRegister = resolveCwd('ts-node/register');
const esm = enableTypeScript === 'esm';
const tsNodeHelper = resolveCwd(esm ? 'ts-node/esm.mjs' : 'ts-node/register');
const nodeExecPath = process.execPath;

if (enableTypeScript && tsNodeRegister) {
options.args = options.args || [];
options.args.unshift(tsNodeRegister);
options.args.unshift('-r');
if (enableTypeScript && tsNodeHelper) {
args.unshift(esm ? '--loader' : '-r', tsNodeHelper);
Object.assign(env, getTsNodeEnv(tsconfig, transpileOnly, esm));

options.env = { ...options.env, ...getTsNodeEnv(tsconfig, transpileOnly) };
logger.info('Executing [TS]: ' + [nodeExecPath, ...(options.args || [])].join(' '));
logger.info('Executing [TS]: ' + [nodeExecPath, ...args].join(' '));
} else {
logger.info('Executing: ' + [nodeExecPath, ...(options.args || [])].join(' '));
logger.info('Executing: ' + [nodeExecPath, ...args].join(' '));
}

return spawn(nodeExecPath, options.args, { stdio: 'inherit', env: options.env, ...spawnOptions });
return spawn(nodeExecPath, args, { stdio: 'inherit', env, ...spawnOptions });
};
}
Loading