Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add --tsconfig-path option for CLI & support extends property in tsconfig.json #914

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"the-answer": "^1.0.0",
"tiny-json-http": "^7.0.2",
"ts-loader": "^9.3.0",
"tsconfck": "^1.2.2",
"tsconfig-paths": "^3.7.0",
"tsconfig-paths-webpack-plugin": "^3.2.0",
"twilio": "^3.23.2",
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Outputs the Node.js compact build of `input.js` into `dist/index.js`.
--license [file] Adds a file containing licensing information to the output
--stats-out [file] Emit webpack stats as json to the specified output file
--target [es] ECMAScript target to use for output (default: es2015)
--tsconfig-path [file] Specify tsconfig.json to use for build (default: resolve tsconfig.json from entrypoint)
Learn more: https://webpack.js.org/configuration/target
-d, --debug Show debug logs
```
Expand Down
12 changes: 8 additions & 4 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Options:
--license [file] Adds a file containing licensing information to the output
--stats-out [file] Emit webpack stats as json to the specified output file
--target [es] ECMAScript target to use for output (default: es2015)
--tsconfig-path [file] Specify tsconfig.json to use for build (default: resolve tsconfig.json from entrypoint)
Learn more: https://webpack.js.org/configuration/target
-d, --debug Show debug logs
`;
Expand Down Expand Up @@ -154,7 +155,8 @@ async function runCmd (argv, stdout, stderr) {
"-t": "--transpile-only",
"--license": String,
"--stats-out": String,
"--target": String
"--target": String,
"--tsconfig-path": String
}, {
permissive: false,
argv
Expand Down Expand Up @@ -250,7 +252,8 @@ async function runCmd (argv, stdout, stderr) {
transpileOnly: args["--transpile-only"],
license: args["--license"],
quiet,
target: args["--target"]
target: args["--target"],
tsconfigPath: args["--tsconfig-path"]
}
);

Expand Down Expand Up @@ -343,8 +346,9 @@ async function runCmd (argv, stdout, stderr) {
}
}
if (args["--watch"]) {
ncc.handler(handler);
ncc.rebuild(() => {
const nccWithWatchOption = await ncc
nccWithWatchOption.handler(handler);
nccWithWatchOption.rebuild(() => {
if (ps)
ps.kill();
startTime = Date.now();
Expand Down
44 changes: 9 additions & 35 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ const webpack = require("webpack");
const MemoryFS = require("memory-fs");
const terser = require("terser");
const tsconfigPaths = require("tsconfig-paths");
const { loadTsconfig } = require("tsconfig-paths/lib/tsconfig-loader");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const shebangRegEx = require('./utils/shebang');
const nccCacheDir = require("./utils/ncc-cache-dir");
const LicenseWebpackPlugin = require('license-webpack-plugin').LicenseWebpackPlugin;
const { version: nccVersion } = require('../package.json');
const { hasTypeModule } = require('./utils/has-type-module');
const { loadTsconfigOptions } = require('./utils/load-tsconfig-options');

// support glob graceful-fs
fs.gracefulify(require("fs"));
Expand All @@ -32,7 +32,7 @@ const defaultPermissions = 0o666;
const relocateLoader = eval('require(__dirname + "/loaders/relocate-loader.js")');

module.exports = ncc;
function ncc (
async function ncc (
entry,
{
cache,
Expand All @@ -57,7 +57,8 @@ function ncc (
production = true,
// webpack defaults to `module` and `main`, but that's
// not really what node.js supports, so we reset it
mainFields = ['main']
mainFields = ['main'],
tsconfigPath = undefined
} = {}
) {
// v8 cache not supported for ES modules
Expand Down Expand Up @@ -108,21 +109,16 @@ function ncc (
existingAssetNames.push(`${filename}.cache`);
existingAssetNames.push(`${filename}.cache${ext}`);
}
const fullTsconfig = await loadTsconfigOptions(tsconfigPath, {
base: process.cwd(),
start: dirname(entry),
filename: 'tsconfig.json'
});
const resolvePlugins = [];
// add TsconfigPathsPlugin to support `paths` resolution in tsconfig
// we need to catch here because the plugin will
// error if there's no tsconfig in the working directory
let fullTsconfig = {};
try {
const configFileAbsolutePath = walkParentDirs({
base: process.cwd(),
start: dirname(entry),
filename: 'tsconfig.json',
});
fullTsconfig = loadTsconfig(configFileAbsolutePath) || {
compilerOptions: {}
};

const tsconfigPathsOptions = { silent: true }
if (fullTsconfig.compilerOptions.allowJs) {
tsconfigPathsOptions.extensions = SUPPORTED_EXTENSIONS
Expand Down Expand Up @@ -668,25 +664,3 @@ function getFlatFiles(mfsData, output, getAssetMeta, tsconfig, curBase = "") {
}
}
}

// Adapted from https://github.com/vercel/vercel/blob/18bec983aefbe2a77bd14eda6fca59ff7e956d8b/packages/build-utils/src/fs/run-user-scripts.ts#L289-L310
function walkParentDirs({
base,
start,
filename,
}) {
let parent = '';

for (let current = start; base.length <= current.length; current = parent) {
const fullPath = join(current, filename);

// eslint-disable-next-line no-await-in-loop
if (fs.existsSync(fullPath)) {
return fullPath;
}

parent = dirname(current);
}

return null;
}
55 changes: 55 additions & 0 deletions src/utils/load-tsconfig-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const { join, dirname, resolve } = require('path');
const fs = require('fs');
const { parse } = require('tsconfck');

const DEFAULT_TSCONFIG_OPTIONS = {
compilerOptions: {}
};

/**
* @typedef {object} LoadTsconfigInit
* @property {string} base
* @property {string} start
* @property {string} filename
*/

/**
* @description Adapted from https://github.com/vercel/vercel/blob/18bec983aefbe2a77bd14eda6fca59ff7e956d8b/packages/build-utils/src/fs/run-user-scripts.ts#L289-L310
* @param {LoadTsconfigInit}
* @returns {string | null}
*/
function walkParentDirs({ base, start, filename }) {
let parent = '';

for (let current = start; base.length <= current.length; current = parent) {
const fullPath = join(current, filename);

if (fs.existsSync(fullPath)) {
return fullPath;
}

parent = dirname(current);
}

return null;
}

/**
* @param {string | undefined} configPath
* @param {LoadTsconfigInit}
* @returns {Promise<object>}
*/
exports.loadTsconfigOptions = async function (configPath, { base, start, filename }) {
// throw error if `configPath` does not exist
const tsconfig = configPath != null ? resolve(configPath) : walkParentDirs({ base, start, filename });
if (tsconfig == null) {
return DEFAULT_TSCONFIG_OPTIONS;
}
try {
const result = await parse(tsconfig);
return result.tsconfig;
} catch (error) {
console.error(error);
throw error;
}
};
10 changes: 10 additions & 0 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ module.exports = [
args: ["run", "-t", "test/fixtures/with-type-errors/ts-error.ts"],
expect: { code: 0 }
},
{
args: ["run", "test/fixtures/ts-extends/any-args.ts"],
expect (code, stdout, stderr) {
return code === 1 && stderr.toString().indexOf('any-args.ts(4,20)') !== -1 && stderr.toString().indexOf('TS7006') !== -1;
}
},
{
args: ["run", "test/fixtures/ts-extends/any-args.ts", "--tsconfig-path", "test/fixtures/ts-extends/tsconfig.build.json"],
expect: { code: 0 }
},
{
args: ["build", "-o", "tmp", "test/fixtures/test.cjs"],
expect (code, stdout, stderr) {
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/ts-extends/any-args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* throws error (TS7006: an implicit 'any' type) if strict options is set to true, or otherwise passes compilation
*/
function something(args) {
return args;
}
6 changes: 6 additions & 0 deletions test/fixtures/ts-extends/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"strict": false
}
}
5 changes: 5 additions & 0 deletions test/fixtures/ts-extends/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"strict": true
}
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14854,6 +14854,11 @@ ts-loader@^9.3.0:
micromatch "^4.0.0"
semver "^7.3.4"

tsconfck@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-1.2.2.tgz#3f7ac55bcd16b8d89ff05ba8e27057f3375828c8"
integrity sha512-x5YpjOqjJnMs1EsJvQBQbrysrY32eGoZRRr5YvbN1hwlrXKc7jiphCOUrT7xbFdOWk8sh+EtMYbGPbTO8rDmcw==

tsconfig-paths-webpack-plugin@^3.2.0:
version "3.5.1"
resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.1.tgz#e4dbf492a20dca9caab60086ddacb703afc2b726"
Expand Down