Skip to content

Commit

Permalink
fix(core): process static imports
Browse files Browse the repository at this point in the history
Enable static imports resolution using `baseUrl` in `tsconfig.json`

This update allows resolving static imports when the `baseUrl` property
is set in `tsconfig.json`. For example, `import { foo } from 'app/main.ts'`
can be resolved easily.

- If `baseUrl` is set to `src`, the path resolves to `./src/app/main.ts`.
- If `baseUrl` is not defined, resolution falls back to checking
  `node_modules`.
  • Loading branch information
rainerhahnekamp authored Sep 11, 2024
1 parent 0ba97bf commit e999253
Show file tree
Hide file tree
Showing 22 changed files with 475 additions and 352 deletions.
4 changes: 0 additions & 4 deletions .release-please-manifest.json

This file was deleted.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@types/eslint": "^8.4.6",
"@types/estree": "^1.0.0",
"@types/node": "18.19.14",
"@typescript-eslint/rule-tester": "^8.5.0",
"@vitest/coverage-v8": "^2.0.3",
"eslint": "^9.6.0",
"eslint-config-prettier": "^9.1.0",
Expand All @@ -38,7 +39,7 @@
"prettier": "^3.2.5",
"ts-node": "10.9.1",
"typescript": "5.5.3",
"typescript-eslint": "8.0.0-alpha.41",
"typescript-eslint": "^8.5.0",
"vitest": "^2.0.3"
}
}
6 changes: 3 additions & 3 deletions packages/core/src/lib/file-info/generate-ts-data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import getFs, { isFsVirtualised } from '../fs/getFs';
import * as ts from 'typescript';
import { TsData } from './ts-data';
import { getTsPathsAndRootDir } from './get-ts-paths-and-root-dir';
import { getTsConfigContext } from './get-ts-config-context';
import { FsPath, toFsPath } from './fs-path';

/**
Expand All @@ -23,7 +23,7 @@ import { FsPath, toFsPath } from './fs-path';
* This will return a paths property of `{'app/*': './src/app'}`
*/
export const generateTsData = (tsConfigPath: FsPath): TsData => {
const { paths, rootDir } = getTsPathsAndRootDir(tsConfigPath);
const configContext = getTsConfigContext(tsConfigPath);

const fs = getFs();
const cwd = fs.getParent(tsConfigPath);
Expand All @@ -38,7 +38,7 @@ export const generateTsData = (tsConfigPath: FsPath): TsData => {

const sys = getTsSys();

return { paths, configObject, cwd, sys, rootDir };
return { ...configContext, configObject, cwd, sys};
};

function getTsSys(): ts.System {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import UnassignedFileInfo from './unassigned-file-info';
import traverseFilesystem from './traverse-filesystem';
import { FsPath } from './fs-path';
import { formatFileInfo } from './format-file-info';
import { logger } from '../log';
import { TsData } from './ts-data';
import { traverseFilesystem } from "./traverse-filesystem";

const log = logger('core.file-info.generate-and-root-dir');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,35 @@ import { FsPath, toFsPath } from './fs-path';
import { TsConfig } from './ts-config';
import { InvalidPathError } from '../error/user-error';

export type TsConfigContext = {
paths: Record<string, FsPath>;
rootDir: FsPath;
baseUrl?: FsPath;
};

/**
* Retrieves the paths variable from a tsconfig and also traverses through
* potential parent configs.
* Parses the tsconfig.json file and returns specific information for
* further processing.
*
* Maps paths from the tsconfig.json to `FilePath` where possible.
* It also traverses through potential parent configs.
* It also resolves the `baseUrl` - if present - to an `FsPath`.
*
* If there are wildcards, the wildcard will be removed from their path value.
* This is necessary to keep up the FsPath type
* This is necessary to keep up the FsPath type.
*
* It matters, if a `baseUrl` exists or not. It is not by default set to
* the root directory of the tsconfig.json. That has implications for the
* TypeScript resolution because static imports only work with a `baseUrl`.
*
* @param tsConfigPath path of the tsconfig.json
*/
export const getTsPathsAndRootDir = (
tsConfigPath: FsPath,
): { paths: Record<string, FsPath>; rootDir: FsPath } => {
export function getTsConfigContext(tsConfigPath: FsPath): TsConfigContext {
const fs = getFs();
let currentTsConfigPath = tsConfigPath;
let currentTsConfigDir = fs.getParent(currentTsConfigPath);
const paths: Record<string, FsPath> = {};
let baseUrl: FsPath | undefined = undefined;

while (currentTsConfigPath) {
const configRawContent = fs.readFile(currentTsConfigPath);
Expand All @@ -29,16 +42,18 @@ export const getTsPathsAndRootDir = (
);

const config = configContent.config as TsConfig;
const baseUrl = config.compilerOptions?.baseUrl ?? './';
currentTsConfigDir = fs.getParent(currentTsConfigPath);
if (baseUrl === undefined && config.compilerOptions?.baseUrl) {
baseUrl = toFsPath(fs.join(currentTsConfigDir, config.compilerOptions.baseUrl))
}

const newPaths: Record<string, string[]> =
config.compilerOptions?.paths ?? {};
currentTsConfigDir = fs.getParent(currentTsConfigPath);
for (const [key, [value]] of Object.entries(newPaths)) {
const valueForFsPath = value.endsWith('/*') ? value.slice(0, -2) : value;
const potentialFilename = fs.join(
currentTsConfigDir,
baseUrl,
config.compilerOptions?.baseUrl ?? './',
valueForFsPath,
);
if (fs.exists(potentialFilename)) {
Expand All @@ -62,5 +77,9 @@ export const getTsPathsAndRootDir = (
}
}

return { paths, rootDir: currentTsConfigDir };
};
return {
paths,
rootDir: currentTsConfigDir,
baseUrl
};
}
137 changes: 0 additions & 137 deletions packages/core/src/lib/file-info/get-ts-paths-and-root-dir.spec.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
import getFs, { useDefaultFs, useVirtualFs } from '../fs/getFs';
import { Fs } from '../fs/fs';
import { isFsPath, toFsPath } from './fs-path';
import getFs, { useDefaultFs, useVirtualFs } from '../../fs/getFs';
import { Fs } from '../../fs/fs';
import { isFsPath, toFsPath } from '../fs-path';
import { describe, beforeEach, beforeAll, it, expect } from 'vitest';

describe('FsPath', () => {
describe('VirtualFs', () => {
Expand Down Expand Up @@ -37,6 +37,6 @@ describe('FsPath', () => {
it('should also allow a directory', () => {
useDefaultFs();
const fs = getFs();
expect(isFsPath(fs.join(__dirname, '../test'))).toBe(true);
expect(isFsPath(fs.join(__dirname, '../tests'))).toBe(true);
});
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createProject } from '../test/project-creator';
import { generateTsData } from './generate-ts-data';
import { describe, it, test, expect } from 'vitest';
import { FileTree } from '../test/project-configurator';
import { toFsPath } from './fs-path';
import { TsPaths } from './ts-data';
import { tsConfig } from '../test/fixtures/ts-config';
import { createProject } from '../../test/project-creator';
import { generateTsData } from '../generate-ts-data';
import { FileTree } from '../../test/project-configurator';
import { toFsPath } from '../fs-path';
import { TsPaths } from '../ts-data';
import { tsConfig } from '../../test/fixtures/ts-config';
import { describe, it, expect, test } from 'vitest';

describe('generateTsData', () => {
function setup(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { describe, expect, it } from 'vitest';
import { generateUnassignedFileInfo } from './generate-unassigned-file-info';
import { createProject } from '../test/project-creator';
import { inVfs } from '../test/in-vfs';
import { toFsPath } from './fs-path';
import { generateTsData } from './generate-ts-data';
import getFs from '../fs/getFs';
import { tsConfig } from '../test/fixtures/ts-config';
import { generateUnassignedFileInfo } from '../generate-unassigned-file-info';
import { createProject } from '../../test/project-creator';
import { inVfs } from '../../test/in-vfs';
import { toFsPath } from '../fs-path';
import { generateTsData } from '../generate-ts-data';
import getFs from '../../fs/getFs';
import { tsConfig } from '../../test/fixtures/ts-config';
import { describe, it, expect } from 'vitest';

describe('Generate File Info', () => {
const getTsData = () =>
Expand Down
Loading

0 comments on commit e999253

Please sign in to comment.