Skip to content

Commit

Permalink
feat: support tsconfig paths (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: Hiroki Osame <hiroki.osame@gmail.com>
  • Loading branch information
error-four-o-four and privatenumber authored Jul 19, 2024
1 parent 6e80985 commit 5f0df84
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/utils/get-rollup-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { esbuildTransform, esbuildMinify } from './rollup-plugins/esbuild.js';
import { externalizeNodeBuiltins } from './rollup-plugins/externalize-node-builtins.js';
import { patchBinary } from './rollup-plugins/patch-binary.js';
import { resolveTypescriptMjsCts } from './rollup-plugins/resolve-typescript-mjs-cjs.js';
import { resolveTsconfigPaths } from './rollup-plugins/resolve-tsconfig-paths.js';
import { stripHashbang } from './rollup-plugins/strip-hashbang.js';
import { getExternalDependencies } from './parse-package-json/get-external-dependencies.js';

Expand All @@ -40,6 +41,7 @@ type Output = OutputOptions[] & Record<string, OutputOptions>;
const getConfig = {
type: async (
options: Options,
tsconfig: TsConfigResult | null,
) => {
const dts = await import('rollup-plugin-dts');

Check warning on line 46 in src/utils/get-rollup-configs.ts

View workflow job for this annotation

GitHub Actions / Release

Maximum number of dependencies (15) exceeded

Expand All @@ -48,6 +50,11 @@ const getConfig = {
preserveEntrySignatures: 'strict' as const,
plugins: [
externalizeNodeBuiltins(options),
...(
tsconfig
? [resolveTsconfigPaths(tsconfig)]
: []
),
resolveTypescriptMjsCts(),
dts.default({
respectExternal: true,
Expand Down Expand Up @@ -90,6 +97,11 @@ const getConfig = {
preserveEntrySignatures: 'strict' as const,
plugins: [
externalizeNodeBuiltins(options),
...(
tsconfig
? [resolveTsconfigPaths(tsconfig)]
: []
),
resolveTypescriptMjsCts(),
alias({
entries: aliases,
Expand Down Expand Up @@ -170,7 +182,7 @@ export const getRollupConfigs = async (
let config = configs.type;

if (!config) {
config = await getConfig.type(flags);
config = await getConfig.type(flags, tsconfig);
config.external = externalTypeDependencies;
configs.type = config;
}
Expand Down
51 changes: 51 additions & 0 deletions src/utils/rollup-plugins/resolve-tsconfig-paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { createPathsMatcher, type TsConfigResult } from 'get-tsconfig';
import type { Plugin } from 'rollup';

const name = 'resolve-tsconfig-paths';

const isRelative = (filePath: string) => filePath[0] === '.';
const isAbsolute = (filePath: string) => filePath[0] === '/' || /^[\s\S]:/.test(filePath);
const isImports = (filePath: string) => filePath[0] === '#';

export const resolveTsconfigPaths = (
tsconfig: TsConfigResult,
): Plugin => {
const pathsMatcher = createPathsMatcher(tsconfig);
if (!pathsMatcher) {
return {
name,
};
}

return {
name,
async resolveId(id, importer, options) {
if (
!importer
|| isRelative(id)
|| isAbsolute(id)
|| isImports(id)
|| id.startsWith('\0')
) {
return null;
}

const possiblePaths = pathsMatcher(id);
for (const tryPath of possiblePaths) {
const resolved = await this.resolve(
tryPath,
importer,
{
skipSelf: true,
...options,
},
);
if (resolved) {
return resolved;
}
}

return null;
},
};
};
95 changes: 94 additions & 1 deletion tests/specs/builds/typescript.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { testSuite, expect } from 'manten';
import { createFixture } from 'fs-fixture';
import { outdent } from 'outdent';
import { pkgroll } from '../../utils.js';
import { createPackageJson, createTsconfigJson } from '../../fixtures.js';
import { createPackageJson, createTsconfigJson, installTypeScript } from '../../fixtures.js';

export default testSuite(({ describe }, nodePath: string) => {
describe('TypeScript', ({ test }) => {
Expand Down Expand Up @@ -52,6 +53,98 @@ export default testSuite(({ describe }, nodePath: string) => {
const content = await fixture.readFile('dist/index.js', 'utf8');
expect(content).toBe('console.log(1);\n');
});

test('resolves baseUrl', async () => {
await using fixture = await createFixture({
src: {
'index.ts': outdent`
import { qux } from 'dir/exportee.js';
import { quux } from 'dir/deep/exportee.js';
console.log(qux, quux);
`,
'importee.ts': 'export const foo = \'foo\'',
dir: {
'importee.ts': 'export const bar = \'bar\'',
'exportee.ts': outdent`
import { foo } from 'importee.js';
import { baz } from 'dir/deep/importee.js';
export const qux = foo + baz;`,
deep: {
'importee.ts': 'export const baz = \'baz\'',
'exportee.ts': outdent`
import { foo } from 'importee.js';
import { bar } from 'dir/importee.js';
import { baz } from 'dir/deep/importee.js';
export const quux = foo + bar + baz;`,
},
},
},
'package.json': createPackageJson({
exports: './dist/index.mjs',
}),
'tsconfig.json': createTsconfigJson({
compilerOptions: {
baseUrl: './src',
},
}),
});

const pkgrollProcess = await pkgroll(['--minify'], {
cwd: fixture.path,
nodePath,
});

expect(pkgrollProcess.exitCode).toBe(0);
expect(pkgrollProcess.stderr).toBe('');

const content = await fixture.readFile('dist/index.mjs', 'utf8');
expect(content).toMatch('"foo"');
expect(content).toMatch('"bar"');
expect(content).toMatch('"baz"');
});

test('resolves paths', async () => {
await using fixture = await createFixture({
...installTypeScript,
src: {
'index.ts': outdent`
import * as foo from '@foo/index.js';
import { bar } from '~bar';
export { foo, bar };`,
foo: {
'index.ts': 'export { a } from \'@foo/a.js\';',
'a.ts': 'export const a = \'a\';',
},
'bar/index.ts': 'export const bar = \'bar\';',
},
'package.json': createPackageJson({
exports: {
types: './dist/index.d.mts',
default: './dist/index.mjs',
},
}),
'tsconfig.json': createTsconfigJson({
compilerOptions: {
paths: {
'@foo/*': ['./src/foo/*'],
'~bar': ['./src/bar/index.ts'],
},
},
}),
});

const pkgrollProcess = await pkgroll(['--minify'], {
cwd: fixture.path,
nodePath,
});

expect(pkgrollProcess.exitCode).toBe(0);
expect(pkgrollProcess.stderr).toBe('');

const content = await fixture.readFile('dist/index.mjs', 'utf8');
expect(content).toMatch('"a"');
expect(content).toMatch('"bar"');
});
});

describe('custom tsconfig.json path', ({ test }) => {
Expand Down

0 comments on commit 5f0df84

Please sign in to comment.