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
30 changes: 24 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -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')

Expand Down Expand Up @@ -42,12 +44,15 @@ function findImports(line: string): string[] | null {
function resolveImports(
file: ReadonlyArray<string>,
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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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'))

Expand Down
22 changes: 20 additions & 2 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ const tests: Record<string, Test> = {
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 },
Expand All @@ -145,6 +145,24 @@ const tests: Record<string, Test> = {
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<void> => {
Expand Down