🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

eslint-import-resolver-typescript

Package Overview
Dependencies
Maintainers
0
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-import-resolver-typescript - npm Package Compare versions

Comparing version

to
4.0.0

lib/constants.d.ts

34

lib/index.d.ts

@@ -1,27 +0,13 @@

import { type NapiResolveOptions, ResolverFactory } from 'rspack-resolver';
export declare const defaultConditionNames: string[];
export declare const defaultExtensions: string[];
export declare const defaultExtensionAlias: {
'.js': string[];
'.jsx': string[];
'.cjs': string[];
'.mjs': string[];
};
export declare const defaultMainFields: string[];
export declare const interfaceVersion = 2;
export interface TsResolverOptions extends NapiResolveOptions {
alwaysTryTypes?: boolean;
project?: string[] | string;
}
export declare function resolve(source: string, file: string, options?: TsResolverOptions | null, resolver?: ResolverFactory | null): {
found: boolean;
path?: string | null;
};
export declare function createTypeScriptImportResolver(options?: TsResolverOptions | null): {
import type { ResolvedResult } from 'eslint-plugin-import-x/types.js';
import { ResolverFactory } from 'rspack-resolver';
import type { TypeScriptResolverOptions } from './types.js';
export * from './constants.js';
export * from './helpers.js';
export * from './normalize-options.js';
export type * from './types.js';
export declare const resolve: (source: string, file: string, options?: TypeScriptResolverOptions | null, resolver?: ResolverFactory | null) => ResolvedResult;
export declare const createTypeScriptImportResolver: (options?: TypeScriptResolverOptions | null) => {
interfaceVersion: number;
name: string;
resolve(source: string, file: string): {
found: boolean;
path?: string | null;
};
resolve(source: string, file: string): ResolvedResult;
};

@@ -1,90 +0,36 @@

import fs from 'node:fs';
import module from 'node:module';
import path from 'node:path';
import isNodeCoreModule from '@nolyfill/is-core-module';
import debug from 'debug';
import { createPathsMatcher, getTsconfig } from 'get-tsconfig';
import { createFilesMatcher, parseTsconfig, } from 'get-tsconfig';
import { isBunModule } from 'is-bun-module';
import { ResolverFactory } from 'rspack-resolver';
import { stableHash } from 'stable-hash';
import { globSync, isDynamicPattern } from 'tinyglobby';
const IMPORTER_NAME = 'eslint-import-resolver-typescript';
const log = debug(IMPORTER_NAME);
export const defaultConditionNames = [
'types',
'import',
'esm2020',
'es2020',
'es2015',
'require',
'node',
'node-addons',
'browser',
'default',
];
export const defaultExtensions = [
'.ts',
'.tsx',
'.d.ts',
'.js',
'.jsx',
'.json',
'.node',
];
export const defaultExtensionAlias = {
'.js': [
'.ts',
'.tsx',
'.d.ts',
'.js',
],
'.jsx': ['.tsx', '.d.ts', '.jsx'],
'.cjs': ['.cts', '.d.cts', '.cjs'],
'.mjs': ['.mts', '.d.mts', '.mjs'],
};
export const defaultMainFields = [
'types',
'typings',
'fesm2020',
'fesm2015',
'esm2020',
'es2020',
'module',
'jsnext:main',
'main',
];
export const interfaceVersion = 2;
const JS_EXT_PATTERN = /\.(?:[cm]js|jsx?)$/;
const RELATIVE_PATH_PATTERN = /^\.{1,2}(?:\/.*)?$/;
let previousOptionsHash;
let optionsHash;
let cachedOptions;
let cachedCwd;
let mappersCachedOptions;
let mappers = [];
let resolverCachedOptions;
let cachedResolver;
export function resolve(source, file, options, resolver) {
if (!cachedOptions ||
previousOptionsHash !== (optionsHash = stableHash(options))) {
previousOptionsHash = optionsHash;
cachedOptions = {
...options,
conditionNames: options?.conditionNames ?? defaultConditionNames,
extensions: options?.extensions ?? defaultExtensions,
extensionAlias: options?.extensionAlias ?? defaultExtensionAlias,
mainFields: options?.mainFields ?? defaultMainFields,
import { IMPORT_RESOLVER_NAME, JS_EXT_PATTERN } from './constants.js';
import { mangleScopedPackage, removeQuerystring, sortProjectsByAffinity, } from './helpers.js';
import { log } from './logger.js';
import { normalizeOptions } from './normalize-options.js';
export * from './constants.js';
export * from './helpers.js';
export * from './normalize-options.js';
const resolverCache = new Map();
const tsconfigCache = new Map();
const matcherCache = new Map();
const oxcResolve = (source, file, resolver) => {
const result = resolver.sync(path.dirname(file), source);
if (result.path) {
return {
found: true,
path: result.path,
};
}
if (!resolver) {
if (!cachedResolver || resolverCachedOptions !== cachedOptions) {
cachedResolver = new ResolverFactory(cachedOptions);
resolverCachedOptions = cachedOptions;
}
resolver = cachedResolver;
if (result.error) {
log('oxc resolve error:', result.error);
}
log('looking for', source, 'in', file);
source = removeQuerystring(source);
if (isNodeCoreModule(source) ||
isBunModule(source, (process.versions.bun ?? 'latest'))) {
return {
found: false,
};
};
export const resolve = (source, file, options, resolver) => {
if (module.isBuiltin(source) ||
(process.versions.bun &&
isBunModule(source, process.versions.bun))) {
log('matched core:', source);

@@ -104,29 +50,74 @@ return {

}
initMappers(cachedOptions);
let mappedPaths = getMappedPaths(source, file, cachedOptions.extensions, true);
if (mappedPaths.length > 0) {
log('matched ts path:', ...mappedPaths);
source = removeQuerystring(source);
options ||= {};
if (!resolver) {
const optionsHash = stableHash(options);
const cwd = process.cwd();
options = normalizeOptions(options, cwd);
const cacheKey = `${optionsHash}:${cwd}`;
let cached = resolverCache.get(cacheKey);
if (!cached && !options.project) {
resolverCache.set(cacheKey, (cached = new ResolverFactory(options)));
}
resolver = cached;
}
else {
mappedPaths = [source];
}
let foundNodePath;
for (const mappedPath of mappedPaths) {
try {
const resolved = resolver.sync(path.dirname(path.resolve(file)), mappedPath);
if (resolved.path) {
foundNodePath = resolved.path;
break;
options ||= {};
createResolver: if (!resolver) {
const project = options.project;
for (const tsconfigPath of project) {
const resolverCached = resolverCache.get(tsconfigPath);
if (resolverCached) {
resolver = resolverCached;
break createResolver;
}
let tsconfigCached = tsconfigCache.get(tsconfigPath);
if (!tsconfigCached) {
tsconfigCache.set(tsconfigPath, (tsconfigCached = parseTsconfig(tsconfigPath)));
}
let matcherCached = matcherCache.get(tsconfigPath);
if (!matcherCached) {
matcherCache.set(tsconfigPath, (matcherCached = createFilesMatcher({
config: tsconfigCached,
path: tsconfigPath,
})));
}
const tsconfig = matcherCached(file);
if (!tsconfig) {
log('tsconfig', tsconfigPath, 'does not match', file);
continue;
}
log('matched tsconfig at:', tsconfigPath, 'for', file);
options = {
...options,
tsconfig: {
references: 'auto',
...options.tsconfig,
configFile: tsconfigPath,
},
};
resolver = new ResolverFactory(options);
resolverCache.set(tsconfigPath, resolver);
break createResolver;
}
catch {
log('failed to resolve with', mappedPath);
log('no tsconfig matched', file, 'with', ...project, ', trying from the the nearest one');
for (const p of sortProjectsByAffinity(project, file)) {
const resolved = resolve(source, file, { ...options, project: p }, resolver);
if (resolved.found) {
return resolved;
}
}
}
if ((JS_EXT_PATTERN.test(foundNodePath) ||
(cachedOptions.alwaysTryTypes && !foundNodePath)) &&
if (!resolver) {
return {
found: false,
};
}
const resolved = oxcResolve(source, file, resolver);
const foundPath = resolved.path;
if (((foundPath && JS_EXT_PATTERN.test(foundPath)) ||
(options.alwaysTryTypes !== false && !foundPath)) &&
!/^@types[/\\]/.test(source) &&
!path.isAbsolute(source) &&
!source.startsWith('.')) {
const definitelyTyped = resolve('@types' + path.sep + mangleScopedPackage(source), file, options);
const definitelyTyped = oxcResolve('@types/' + mangleScopedPackage(source), file, resolver);
if (definitelyTyped.found) {

@@ -136,25 +127,16 @@ return definitelyTyped;

}
if (foundNodePath) {
log('matched node path:', foundNodePath);
return {
found: true,
path: foundNodePath,
};
if (foundPath) {
log('matched path:', foundPath);
}
log("didn't find ", source);
else {
log("didn't find", source, 'with', options.tsconfig?.configFile || options.project);
}
return resolved;
};
export const createTypeScriptImportResolver = (options) => {
options = normalizeOptions(options);
const resolver = options.project ? null : new ResolverFactory(options);
return {
found: false,
};
}
export function createTypeScriptImportResolver(options) {
const resolver = new ResolverFactory({
...options,
conditionNames: options?.conditionNames ?? defaultConditionNames,
extensions: options?.extensions ?? defaultExtensions,
extensionAlias: options?.extensionAlias ?? defaultExtensionAlias,
mainFields: options?.mainFields ?? defaultMainFields,
});
return {
interfaceVersion: 3,
name: IMPORTER_NAME,
name: IMPORT_RESOLVER_NAME,
resolve(source, file) {

@@ -164,207 +146,3 @@ return resolve(source, file, options, resolver);

};
}
function removeQuerystring(id) {
const querystringIndex = id.lastIndexOf('?');
if (querystringIndex !== -1) {
return id.slice(0, querystringIndex);
}
return id;
}
const isFile = (path) => {
try {
return !!(path && fs.statSync(path, { throwIfNoEntry: false })?.isFile());
}
catch {
return false;
}
};
const isModule = (modulePath) => !!modulePath && isFile(path.resolve(modulePath, 'package.json'));
function getMappedPaths(source, file, extensions = defaultExtensions, retry) {
const originalExtensions = extensions;
extensions = ['', ...extensions];
let paths = [];
if (RELATIVE_PATH_PATTERN.test(source)) {
const resolved = path.resolve(path.dirname(file), source);
if (isFile(resolved)) {
paths = [resolved];
}
}
else {
let mapperFns = mappers
.filter(({ files }) => files.has(file))
.map(({ mapperFn }) => mapperFn);
if (mapperFns.length === 0) {
mapperFns = mappers
.map(mapper => ({
mapperFn: mapper.mapperFn,
counter: equalChars(path.dirname(file), path.dirname(mapper.path)),
}))
.sort((a, b) => b.counter - a.counter)
.map(({ mapperFn }) => mapperFn);
}
paths = mapperFns
.map(mapperFn => mapperFn(source).map(item => [
...extensions.map(ext => `${item}${ext}`),
...originalExtensions.map(ext => `${item}/index${ext}`),
]))
.flat(2)
.map(toNativePathSeparator)
.filter(mappedPath => {
try {
const stat = fs.statSync(mappedPath, { throwIfNoEntry: false });
if (stat === undefined)
return false;
if (stat.isFile())
return true;
if (stat.isDirectory()) {
return isModule(mappedPath);
}
}
catch {
return false;
}
return false;
});
}
if (retry && paths.length === 0) {
const isJs = JS_EXT_PATTERN.test(source);
if (isJs) {
const jsExt = path.extname(source);
const tsExt = jsExt.replace('js', 'ts');
const basename = source.replace(JS_EXT_PATTERN, '');
let resolved = getMappedPaths(basename + tsExt, file);
if (resolved.length === 0 && jsExt === '.js') {
const tsxExt = jsExt.replace('js', 'tsx');
resolved = getMappedPaths(basename + tsxExt, file);
}
if (resolved.length === 0) {
resolved = getMappedPaths(basename + '.d' + (tsExt === '.tsx' ? '.ts' : tsExt), file);
}
if (resolved.length > 0) {
return resolved;
}
}
for (const ext of extensions) {
const mappedPaths = isJs ? [] : getMappedPaths(source + ext, file);
const resolved = mappedPaths.length > 0
? mappedPaths
: getMappedPaths(source + `/index${ext}`, file);
if (resolved.length > 0) {
return resolved;
}
}
}
return paths;
}
function initMappers(options) {
if (mappers.length > 0 &&
mappersCachedOptions === options &&
cachedCwd === process.cwd()) {
return;
}
cachedCwd = process.cwd();
const configPaths = (typeof options.project === 'string'
? [options.project]
:
Array.isArray(options.project)
? options.project
: [cachedCwd])
.map(config => replacePathSeparator(config, path.sep, path.posix.sep));
const defaultInclude = ['**/*'];
const defaultIgnore = ['**/node_modules/**'];
const projectPaths = [
...new Set([
...configPaths
.filter(p => !isDynamicPattern(p))
.map(p => path.resolve(process.cwd(), p)),
...globSync(configPaths.filter(path => isDynamicPattern(path)), {
absolute: true,
dot: true,
expandDirectories: false,
ignore: defaultIgnore,
}),
]),
];
mappers = projectPaths
.map(projectPath => {
let tsconfigResult;
if (isFile(projectPath)) {
const { dir, base } = path.parse(projectPath);
tsconfigResult = getTsconfig(dir, base);
}
else {
tsconfigResult = getTsconfig(projectPath);
}
if (!tsconfigResult) {
return;
}
const mapperFn = createPathsMatcher(tsconfigResult);
if (!mapperFn) {
return;
}
const files = tsconfigResult.config.files == null &&
tsconfigResult.config.include == null
?
globSync(defaultInclude, {
absolute: true,
cwd: path.dirname(tsconfigResult.path),
dot: true,
ignore: [
...(tsconfigResult.config.exclude ?? []),
...defaultIgnore,
],
})
: [
...(tsconfigResult.config.files != null &&
tsconfigResult.config.files.length > 0
? tsconfigResult.config.files.map(file => path.normalize(path.resolve(path.dirname(tsconfigResult.path), file)))
: []),
...(tsconfigResult.config.include != null &&
tsconfigResult.config.include.length > 0
? globSync(tsconfigResult.config.include, {
absolute: true,
cwd: path.dirname(tsconfigResult.path),
dot: true,
ignore: [
...(tsconfigResult.config.exclude ?? []),
...defaultIgnore,
],
})
: []),
];
return {
path: toNativePathSeparator(tsconfigResult.path),
files: new Set(files.map(toNativePathSeparator)),
mapperFn,
};
})
.filter(Boolean);
mappersCachedOptions = options;
}
function mangleScopedPackage(moduleName) {
if (moduleName.startsWith('@')) {
const replaceSlash = moduleName.replace(path.sep, '__');
if (replaceSlash !== moduleName) {
return replaceSlash.slice(1);
}
}
return moduleName;
}
function replacePathSeparator(p, from, to) {
return from === to ? p : p.replaceAll(from, to);
}
function toNativePathSeparator(p) {
return replacePathSeparator(p, path[process.platform === 'win32' ? 'posix' : 'win32'].sep, path[process.platform === 'win32' ? 'win32' : 'posix'].sep);
}
function equalChars(a, b) {
if (a.length === 0 || b.length === 0) {
return 0;
}
let i = 0;
const length = Math.min(a.length, b.length);
while (i < length && a.charAt(i) === b.charAt(i)) {
i += 1;
}
return i;
}
//# sourceMappingURL=index.js.map
{
"name": "eslint-import-resolver-typescript",
"version": "3.9.1",
"version": "4.0.0",
"type": "module",

@@ -14,3 +14,3 @@ "description": "This plugin adds `TypeScript` support to `eslint-plugin-import`",

"engines": {
"node": "^14.18.0 || >=16.0.0"
"node": "^16.17.0 || >=18.6.0"
},

@@ -22,15 +22,10 @@ "main": "lib/index.cjs",

"types": "./lib/index.d.ts",
"es2020": "./lib/index.es2020.mjs",
"fesm2020": "./lib/index.es2020.mjs",
"import": "./lib/index.js",
"require": "./lib/index.cjs"
"require": "./lib/index.cjs",
"default": "./lib/index.js"
},
"./package.json": "./package.json"
},
"es2020": "lib/index.es2020.mjs",
"fesm2020": "lib/index.es2020.mjs",
"types": "lib/index.d.ts",
"files": [
"lib",
"shim.d.ts",
"!**/*.tsbuildinfo"

@@ -59,7 +54,6 @@ ],

"dependencies": {
"@nolyfill/is-core-module": "1.0.39",
"debug": "^4.4.0",
"get-tsconfig": "^4.10.0",
"is-bun-module": "^1.3.0",
"rspack-resolver": "^1.1.0",
"rspack-resolver": "^1.1.2",
"stable-hash": "^0.0.5",

@@ -66,0 +60,0 @@ "tinyglobby": "^0.2.12"

@@ -28,4 +28,8 @@ # eslint-import-resolver-typescript

- [Installation](#installation)
- [`eslint-plugin-import`](#eslint-plugin-import)
- [`eslint-plugin-import-x`](#eslint-plugin-import-x)
- [Configuration](#configuration)
- [Options from `enhanced-resolve`](#options-from-enhanced-resolve)
- [`eslint.config.js`](#eslintconfigjs)
- [`.eslintrc`](#eslintrc)
- [Options from `rspack-resolver`](#options-from-rspack-resolver)
- [`conditionNames`](#conditionnames)

@@ -51,2 +55,4 @@ - [`extensions`](#extensions)

### `eslint-plugin-import`
```sh

@@ -63,4 +69,15 @@ # npm

**Important when using `eslint-plugin-import-x` and `npm`**: Use `npm i -D eslint-plugin-import@eslint-plugin-import-x@latest eslint-import-resolver-typescript`, or you will end up with both `eslint-plugin-import` and `eslint-plugin-import-x` in your node_modules.
### `eslint-plugin-import-x`
```sh
# npm
npm i -D eslint-plugin-import-x eslint-import-resolver-typescript
# pnpm
pnpm i -D eslint-plugin-import-x eslint-import-resolver-typescript
# yarn
yarn add -D eslint-plugin-import-x eslint-import-resolver-typescript
```
## Configuration

@@ -73,8 +90,6 @@

```js
// eslint.config.js
const {
createTypeScriptImportResolver,
} = require('eslint-import-resolver-typescript')
// eslint.config.js, CommonJS is also supported
import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'
module.exports = [
export default [
{

@@ -107,2 +122,5 @@ settings: {

],
// use <root>/jsconfig.json
project: 'jsconfig.json',
}),

@@ -118,4 +136,4 @@ ],

```js
// eslint.config.js
module.exports = [
// eslint.config.js, CommonJS is also supported
export default [
{

@@ -148,2 +166,5 @@ settings: {

],
// use <root>/jsconfig.json
project: 'jsconfig.json',
},

@@ -196,2 +217,5 @@ },

],
// use <root>/jsconfig.json
"project": "jsconfig.json",
},

@@ -203,3 +227,3 @@ },

## Options from [`enhanced-resolve`][]
## Options from [`rspack-resolver`][]

@@ -288,3 +312,3 @@ ### `conditionNames`

You can pass through other options of [`enhanced-resolve`][] directly
You can pass through other options of [`rspack-resolver`][] directly

@@ -306,2 +330,4 @@ ### Default options

[![Sponsors](https://raw.githubusercontent.com/1stG/static/master/sponsors.svg)](https://github.com/sponsors/JounQin)
## Sponsors

@@ -329,4 +355,4 @@

[`eslint-plugin-import-x`]: https://github.com/un-ts/eslint-plugin-import-x
[`enhanced-resolve`]: https://github.com/webpack/enhanced-resolve
[`rspack-resolver`]: https://github.com/unrs/rspack-resolver
[`typescript`]: https://www.typescriptlang.org
[isc]: https://opensource.org/licenses/ISC

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet