From 06a86cf0dc9c1a2cb588f7424cc05731ba8ff74d Mon Sep 17 00:00:00 2001 From: Egor Date: Wed, 3 May 2023 19:47:19 +0300 Subject: [PATCH] Support AMD imports with baseUrl and without paths in ts config --- src/index.ts | 30 ++++++++++++++++++++++++------ test/index.test.ts | 22 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5bf7fb6..d730dba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,8 @@ import path from 'path' import { TransformCallback, Transform } from 'stream' import ts from 'typescript' +import fs from 'fs' +import { builtinModules } from 'module' import File = require('vinyl') @@ -42,12 +44,15 @@ function findImports(line: string): string[] | null { function resolveImports( file: ReadonlyArray, imports: FileData[], - options: ts.CompilerOptions + options: ts.CompilerOptions, + nodeModules: string[] ): string[] { const { baseUrl, paths, cwd } = options + const base = path.join(cwd as string, path.relative(cwd as string, baseUrl || './')) + const aliases: { [key: string]: string[] | undefined } = {} - for (const alias in paths) { + for (const alias in paths || {}) { /* istanbul ignore else */ if (paths.hasOwnProperty(alias)) { let resolved = alias @@ -82,11 +87,17 @@ function resolveImports( } } + if (resolved.length < 1 && /^\w/.test(imported.import) && !paths) { + const dirName = imported.import.split('/')[0] + if (!nodeModules.includes(dirName) && !builtinModules.includes(dirName)) { + resolved = path.join(base, './' + imported.import) + } + } + if (resolved.length < 1) { continue } - const base = path.join(cwd as string, path.relative(cwd as string, baseUrl || './')) const current = path.relative(base, path.dirname(imported.path)) const target = path.relative(base, resolved) @@ -133,14 +144,21 @@ const alias: AliasPlugin = ({ config, cwd }: PluginOptions) => { const compilerOptions = resolveConfig(config, cwd) - if (!compilerOptions.paths) { - throw new Error("Unable to find the 'paths' property in the supplied configuration!") + if (!compilerOptions.paths && !compilerOptions.baseUrl) { + throw new Error( + "Unable to find the 'paths' or 'baseUrl' property in the supplied configuration!" + ) } if (compilerOptions.baseUrl === undefined || compilerOptions.baseUrl === '.') { compilerOptions.baseUrl = './' } + let nodeModules: string[] = [] + if (!compilerOptions.paths && compilerOptions.baseUrl) { + nodeModules = fs.readdirSync(path.join(cwd, 'node_modules')) + } + compilerOptions.cwd = cwd return new Transform({ @@ -168,7 +186,7 @@ const alias: AliasPlugin = ({ config, cwd }: PluginOptions) => { return callback(undefined, file) } - const resolved = resolveImports(lines, imports, compilerOptions) + const resolved = resolveImports(lines, imports, compilerOptions, nodeModules) file.contents = Buffer.from(resolved.join('\n')) diff --git a/test/index.test.ts b/test/index.test.ts index f055ca1..19c82fb 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -134,9 +134,9 @@ const tests: Record = { error: "Could not find a valid 'tsconfig.json'", }, ["should error with no 'paths' in config"]: { - options: { config: { ...config, paths: undefined } }, + options: { config: { paths: undefined, baseUrl: undefined } }, path: './src/pages/Page.ts', - error: "Unable to find the 'paths' property in the supplied configuration!", + error: "Unable to find the 'paths' or 'baseUrl' property in the supplied configuration!", }, ["should error with no 'path' supplied"]: { options: { config }, @@ -145,6 +145,24 @@ const tests: Record = { output: '', error: 'Received file with no path. Files must have path to be resolved.', }, + ['should replace to relative path when config with baseUrl but without Paths']: { + options: { config: { baseUrl: './src' } }, + path: './src/pages/Page.ts', + input: "import {Grid} from 'components/grid'", + output: "import {Grid} from '../components/grid'", + }, + ['should ignore node module']: { + options: { config: { baseUrl: './src' } }, + path: './src/pages/Page.ts', + input: "import File from 'vinyl'", + output: "import File from 'vinyl'", + }, + ['should ignore builtin module']: { + options: { config: { baseUrl: './src' } }, + path: './src/pages/Page.ts', + input: "import assert from 'assert'", + output: "import assert from 'assert'", + }, } const run = async (test: Test): Promise => {