Skip to content

Commit

Permalink
Add Support for Resolving .cjs, .mjs, .cts and .mts Files (#1503
Browse files Browse the repository at this point in the history
)

* resolve: Pass implied module kind to typescript

* resolve: Fix detection of declaration files

* test: Replace inexistent package

* test: Fix broken docker image

* devcontainer: Update outdated settings

* resolve: Allow `.cts`, `.mts`, `.cjs` and `.mjs`

* resolve: Fix broken `enhanced-resolve` calls

* resolve: Improve type safety

* interop: Create a separate regex for declarations

* types: Remove unnecessary return type

* test: Add remark on how to regenerate tests

* test: Regenerate comparison-tests

* Bump the version number

* Add changelog entry

* doc: Update CHANGELOG.md

Co-authored-by: John Reilly <johnny_reilly@hotmail.com>

Co-authored-by: John Reilly <johnny_reilly@hotmail.com>
  • Loading branch information
manuth and johnnyreilly authored Sep 19, 2022
1 parent 69a9c23 commit a810470
Show file tree
Hide file tree
Showing 57 changed files with 137 additions and 129 deletions.
8 changes: 7 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/zsh"
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/bin/zsh",
"icon": "terminal-bash"
}
},
"terminal.integrated.defaultProfile.linux": "zsh",
},

// Add the IDs of extensions you want installed when the container is created.
Expand Down
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.devcontainer
.git
.github
.vscode
.test
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v9.4.0

* [Add Support for Resolving `.cjs`, `.mjs`, `.cts` and `.mts` Files](https://github.com/TypeStrong/ts-loader/pull/1503) [#1503] - thanks @manuth

## v9.3.1

* [Bug fix: Generate declaration files for js files if allowJs is set to true](https://github.com/TypeStrong/ts-loader/pull/1483) [#1260] - thanks @hediet and @mvilliger
Expand Down
8 changes: 7 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ RUN apt-get update && apt-get install -y wget --no-install-recommends \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install -y google-chrome-unstable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst ttf-freefont \
&& apt-get install -y google-chrome-unstable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get purge --auto-remove -y curl \
&& rm -rf /src/*.deb

WORKDIR /TypeStrong/ts-loader
COPY .git /TypeStrong/ts-loader/.git

# install packages
COPY package.json yarn.lock index.js /TypeStrong/ts-loader/
Expand All @@ -32,3 +33,8 @@ COPY test /TypeStrong/ts-loader/test
# build and run tests with:
# docker build -t ts-loader .
# docker run -it ts-loader yarn test

# regenerate comparison-tests with:
# docker build -t ts-loader .
# docker run -v $(pwd):/TypeStrong/ts-loader -it ts-loader yarn build
# docker run -v $(pwd):/TypeStrong/ts-loader -it ts-loader yarn run comparison-tests --save-output
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-loader",
"version": "9.3.1",
"version": "9.4.0",
"description": "TypeScript loader for webpack",
"main": "index.js",
"types": "dist",
Expand Down
15 changes: 8 additions & 7 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ export const LineFeedCode = 1;

export const extensionRegex = /\.[^.]+$/;
export const tsxRegex = /\.tsx$/i;
export const tsTsxRegex = /\.ts(x?)$/i;
export const dtsDtsxOrDtsDtsxMapRegex = /\.d\.ts(x?)(\.map)?$/i;
export const dtsTsTsxRegex = /(\.d)?\.ts(x?)$/i;
export const dtsTsTsxJsJsxRegex = /((\.d)?\.ts(x?)|js(x?))$/i;
export const tsTsxJsJsxRegex = /\.tsx?$|\.jsx?$/i;
export const jsJsx = /\.js(x?)$/i;
export const jsJsxMap = /\.js(x?)\.map$/i;
export const tsTsxRegex = /\.([cm]?ts|tsx)$/i;
export const declarationRegex = /\.d\.([cm]?ts|tsx)$/i;
export const dtsDtsxOrDtsDtsxMapRegex = /\.d\.([cm]?ts|tsx)(\.map)?$/i;
export const dtsTsTsxRegex = /(\.d)?\.([cm]?ts|tsx)$/i;
export const dtsTsTsxJsJsxRegex = /((\.d)?\.([cm]?[tj]s|[tj]sx))$/i;
export const tsTsxJsJsxRegex = /\.([cm]?[tj]s|[tj]sx)$/i;
export const jsJsx = /\.([cm]?js|jsx)$/i;
export const jsJsxMap = /\.([cm]?js|jsx)\.map$/i;
export const jsonRegex = /\.json$/i;
export const nodeModules = /node_modules/i;
17 changes: 11 additions & 6 deletions src/instances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import * as webpack from 'webpack';
import { makeAfterCompile } from './after-compile';
import { getCompiler, getCompilerOptions } from './compilerSetup';
import { getConfigFile, getConfigParseResult } from './config';
import { dtsDtsxOrDtsDtsxMapRegex, EOL, tsTsxRegex } from './constants';
import {
declarationRegex,
dtsDtsxOrDtsDtsxMapRegex,
EOL,
tsTsxRegex,
} from './constants';
import { getTSInstanceFromCache, setTSInstanceInCache } from './instance-cache';
import { FilePathKey, LoaderOptions, TSFiles, TSInstance } from './interfaces';
import * as logger from './logger';
Expand Down Expand Up @@ -448,13 +453,13 @@ function getScriptRegexp(instance: TSInstance) {
if (instance.configParseResult.options.resolveJsonModule) {
// if allowJs is set then we should accept js(x) files
return instance.configParseResult.options.allowJs === true
? /\.tsx?$|\.json$|\.jsx?$/i
: /\.tsx?$|\.json$/i;
? /\.([cm]?[tj]s|[tj]sx|json)$/i
: /\.([cm]?ts|tsx|json)$/i;
}
// if allowJs is set then we should accept js(x) files
return instance.configParseResult.options.allowJs === true
? /\.tsx?$|\.jsx?$/i
: /\.tsx?$/i;
? /\.([cm]?[tj]s|[tj]sx)$/i
: /\.([cm]?ts|tsx)$/i;
}

export function reportTranspileErrors(
Expand Down Expand Up @@ -682,7 +687,7 @@ export function getInputFileNameFromOutput(
instance: TSInstance,
filePath: string
): string | undefined {
if (filePath.match(tsTsxRegex) && !fileExtensionIs(filePath, '.d.ts')) {
if (filePath.match(tsTsxRegex) && !declarationRegex.test(filePath)) {
return undefined;
}
if (instance.solutionBuilderHost) {
Expand Down
9 changes: 4 additions & 5 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ export function makeResolver(
return create.sync(options.resolve);
}

export type ResolveSync = (
context: string | undefined,
path: string,
moduleName: string
) => string | false;
export type ResolveSync = {
(context: any, path: string, moduleName: string): string | false;
(path: string, moduleName: string): string | false;
};
66 changes: 39 additions & 27 deletions src/servicesHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,28 +260,32 @@ function makeResolvers<T extends typescript.ModuleResolutionHost>(
instance
);

const resolveModuleNames = (
moduleNames: string[],
containingFile: string,
_reusedNames?: string[] | undefined,
redirectedReference?: typescript.ResolvedProjectReference | undefined
): (typescript.ResolvedModule | undefined)[] => {
const resolvedModules = moduleNames.map(moduleName =>
resolveModule(
resolveSync,
resolveModuleName,
appendTsTsxSuffixesIfRequired,
scriptRegex,
moduleName,
containingFile,
redirectedReference
)
);
const resolveModuleNames: typescript.ProgramHost<typescript.BuilderProgram>['resolveModuleNames'] =
(
moduleNames,
containingFile,
_reusedNames?,
redirectedReference?,
_?,
containingSourceFile?
) => {
const resolvedModules = moduleNames.map(moduleName =>
resolveModule(
resolveSync,
resolveModuleName,
appendTsTsxSuffixesIfRequired,
scriptRegex,
moduleName,
containingFile,
redirectedReference,
containingSourceFile
)
);

populateDependencyGraph(resolvedModules, instance, containingFile);
populateDependencyGraph(resolvedModules, instance, containingFile);

return resolvedModules;
};
return resolvedModules;
};

const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective(
compiler,
Expand Down Expand Up @@ -1249,13 +1253,13 @@ function resolveModule(
scriptRegex: RegExp,
moduleName: string,
containingFile: string,
redirectedReference: typescript.ResolvedProjectReference | undefined
redirectedReference: typescript.ResolvedProjectReference | undefined,
containingSourceFile: typescript.SourceFile | undefined
) {
let resolutionResult: ResolvedModule;

try {
const originalFileName = resolveSync(
undefined,
path.normalize(path.dirname(containingFile)),
moduleName
);
Expand All @@ -1272,7 +1276,8 @@ function resolveModule(
const tsResolution = resolveModuleName(
moduleName,
containingFile,
redirectedReference
redirectedReference,
containingSourceFile
);
if (tsResolution.resolvedModule !== undefined) {
const resolvedFileName = path.normalize(
Expand All @@ -1297,7 +1302,8 @@ function resolveModule(
type ResolveModuleName = (
moduleName: string,
containingFile: string,
redirectedReference: typescript.ResolvedProjectReference | undefined
redirectedReference: typescript.ResolvedProjectReference | undefined,
containingSourceFile: typescript.SourceFile | undefined
) => typescript.ResolvedModuleWithFailedLookupLocations;

function makeResolveModuleName(
Expand All @@ -1314,14 +1320,20 @@ function makeResolveModuleName(
moduleResolutionHost
);
}
return (moduleName, containingFile, redirectedReference) =>
return (
moduleName,
containingFileName,
redirectedReference,
containingFile
) =>
compiler.resolveModuleName(
moduleName,
containingFile,
containingFileName,
compilerOptions,
moduleResolutionHost,
instance.moduleResolutionCache,
redirectedReference
redirectedReference,
containingFile?.impliedNodeFormat
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
asset bundle.js 2.6 KiB [emitted] (name: main)
./app.ts 120 bytes [built] [code generated] [2 errors]
./app.ts 120 bytes [built] [code generated] [1 error]
./common/components/myComponent.ts 46 bytes [built] [code generated]

ERROR in app.ts
./app.ts 1:29-53
[tsl] ERROR in app.ts(1,30)
 TS2307: Cannot find module 'components/myComponent' or its corresponding type declarations.
ts-loader-default_609318b4f68865d3

ERROR in app.ts
./app.ts 2:30-55
[tsl] ERROR in app.ts(2,31)
 TS2307: Cannot find module 'components/myComponent2' or its corresponding type declarations.
ts-loader-default_609318b4f68865d3

webpack compiled with 2 errors
webpack compiled with 1 error
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
asset bundle.js 2.6 KiB [emitted] (name: main)
cached modules 120 bytes [cached] 1 module
./app.ts 120 bytes [built] [code generated] [1 error]
./common/components/myComponent.ts 45 bytes [built] [code generated]

ERROR in app.ts
./app.ts 1:29-53
[tsl] ERROR in app.ts(1,30)
 TS2307: Cannot find module 'components/myComponent' or its corresponding type declarations.
ts-loader-default_609318b4f68865d3

ERROR in app.ts
./app.ts 2:30-55
[tsl] ERROR in app.ts(2,31)
 TS2307: Cannot find module 'components/myComponent2' or its corresponding type declarations.
ts-loader-default_609318b4f68865d3

webpack compiled with 2 errors
webpack compiled with 1 error
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
asset bundle.js 2.6 KiB [emitted] (name: main)
./app.ts 120 bytes [built] [code generated] [2 errors]
./app.ts 120 bytes [built] [code generated] [1 error]
./common/components/myComponent.ts 46 bytes [built] [code generated]

ERROR in app.ts
./app.ts 1:29-53
Does not compute.... code: 2307,severity: error,content: Cannot find module 'components/myComponent' or its corresponding type declarations.,file: app.ts,line: 1,character: 30,context: .test/errorFormatter
ts-loader-default_85b0565984bbe8dd

ERROR in app.ts
./app.ts 2:30-55
Does not compute.... code: 2307,severity: error,content: Cannot find module 'components/myComponent2' or its corresponding type declarations.,file: app.ts,line: 2,character: 31,context: .test/errorFormatter
ts-loader-default_85b0565984bbe8dd

webpack compiled with 2 errors
webpack compiled with 1 error
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
asset bundle.js 2.59 KiB [emitted] (name: main)
./app.ts 101 bytes [built] [code generated] [1 error]
./app.ts 101 bytes [built] [code generated]
./fake.ts 165 bytes [built] [code generated]

ERROR in app.ts
./app.ts 1:29-34
[tsl] ERROR in app.ts(1,30)
 TS2307: Cannot find module 'api' or its corresponding type declarations.
ts-loader-default_609318b4f68865d3

webpack compiled with 1 error
webpack compiled successfully
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ eval("\nexports.__esModule = true;\nvar a = __webpack_require__(/*! a */ \"./nod
\*********************************/
/***/ (() => {

eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /nodeModulesMeaningfulErrorWhenImportingTs/node_modules/a/index.ts. By default, ts-loader will not compile .ts files in node_modules./nYou should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option./nSee: https://github.com/Microsoft/TypeScript/issues/12358/n at makeSourceMapAndFinish (/home/john/code/github/ts-loader/dist/index.js:52:18)/n at successLoader (/home/john/code/github/ts-loader/dist/index.js:39:5)/n at Object.loader (/home/john/code/github/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./node_modules/a/index.ts?");
eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /nodeModulesMeaningfulErrorWhenImportingTs/node_modules/a/index.ts. By default, ts-loader will not compile .ts files in node_modules./nYou should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option./nSee: https://github.com/Microsoft/TypeScript/issues/12358/n at makeSourceMapAndFinish (/TypeStrong/ts-loader/dist/index.js:52:18)/n at successLoader (/TypeStrong/ts-loader/dist/index.js:39:5)/n at Object.loader (/TypeStrong/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./node_modules/a/index.ts?");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
asset bundle.js 3.14 KiB [emitted] (name: main)
asset bundle.js 3.1 KiB [emitted] (name: main)
./app.ts 79 bytes [built] [code generated]
./node_modules/a/index.ts 39 bytes [built] [code generated]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ eval("\nexports.__esModule = true;\nvar lib_1 = __webpack_require__(/*! ./lib */
\**********************/
/***/ (() => {

eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /projectReferencesMultiple/lib/index.ts. The most common cause for this is having errors when building referenced projects./n at makeSourceMapAndFinish (/home/john/code/github/ts-loader/dist/index.js:52:18)/n at successLoader (/home/john/code/github/ts-loader/dist/index.js:39:5)/n at Object.loader (/home/john/code/github/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./lib/index.ts?");
eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /projectReferencesMultiple/lib/index.ts. The most common cause for this is having errors when building referenced projects./n at makeSourceMapAndFinish (/TypeStrong/ts-loader/dist/index.js:52:18)/n at successLoader (/TypeStrong/ts-loader/dist/index.js:39:5)/n at Object.loader (/TypeStrong/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./lib/index.ts?");

/***/ }),

Expand All @@ -36,7 +36,7 @@ eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeS
\************************/
/***/ (() => {

eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /projectReferencesMultiple/utils/index.ts. The most common cause for this is having errors when building referenced projects./n at makeSourceMapAndFinish (/home/john/code/github/ts-loader/dist/index.js:52:18)/n at successLoader (/home/john/code/github/ts-loader/dist/index.js:39:5)/n at Object.loader (/home/john/code/github/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./utils/index.ts?");
eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /projectReferencesMultiple/utils/index.ts. The most common cause for this is having errors when building referenced projects./n at makeSourceMapAndFinish (/TypeStrong/ts-loader/dist/index.js:52:18)/n at successLoader (/TypeStrong/ts-loader/dist/index.js:39:5)/n at Object.loader (/TypeStrong/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./utils/index.ts?");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ assets by path unreferencedIndirect/ 1.42 KiB
asset unreferencedIndirect/tsconfig.tsbuildinfo 1.16 KiB [compared for emit]
asset unreferencedIndirect/index.js 209 bytes [compared for emit]
asset unreferencedIndirect/index.d.ts 56 bytes [compared for emit]
asset bundle.js 3.73 KiB [emitted] (name: main)
asset bundle.js 3.65 KiB [emitted] (name: main)
asset indirectWithError/tsconfig.tsbuildinfo 1.33 KiB [compared for emit]
asset lib/tsconfig.tsbuildinfo 1.33 KiB [compared for emit]
./app.ts 187 bytes [built] [code generated]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ eval("\nexports.__esModule = true;\nexports.lib = void 0;\nexports.lib = {\n
\************************/
/***/ (() => {

eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /projectReferencesMultiple/utils/index.ts. The most common cause for this is having errors when building referenced projects./n at makeSourceMapAndFinish (/home/john/code/github/ts-loader/dist/index.js:52:18)/n at successLoader (/home/john/code/github/ts-loader/dist/index.js:39:5)/n at Object.loader (/home/john/code/github/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./utils/index.ts?");
eval("throw new Error(\"Module build failed (from ../../index.js):/nError: TypeScript emitted no output for /projectReferencesMultiple/utils/index.ts. The most common cause for this is having errors when building referenced projects./n at makeSourceMapAndFinish (/TypeStrong/ts-loader/dist/index.js:52:18)/n at successLoader (/TypeStrong/ts-loader/dist/index.js:39:5)/n at Object.loader (/TypeStrong/ts-loader/dist/index.js:22:5)\");\n\n//# sourceURL=webpack:///./utils/index.ts?");

/***/ })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ assets by status 369 bytes [compared for emit]
assets by path lib/*.ts 123 bytes
asset lib/index.d.ts 84 bytes [compared for emit]
asset lib/fileWithError.d.ts 39 bytes [compared for emit]
assets by status 4.72 KiB [emitted]
asset bundle.js 3.39 KiB [emitted] (name: main)
assets by status 4.68 KiB [emitted]
asset bundle.js 3.35 KiB [emitted] (name: main)
asset lib/tsconfig.tsbuildinfo 1.33 KiB [emitted]
./app.ts 187 bytes [built] [code generated]
./lib/index.ts 119 bytes [built] [code generated]
Expand Down
Loading

0 comments on commit a810470

Please sign in to comment.