From a0386f51fe8195d385f696f937d126e76aca71a7 Mon Sep 17 00:00:00 2001 From: Austin Ziegler Date: Fri, 1 Mar 2024 17:00:42 -0500 Subject: [PATCH] Disable `composite` for type declarations We are using pkgroll with Typescript monorepos (managed by pnpm workspaces) and project references. The latter requires `compilerOptions.composite = true` in referenced projects for most `tsc` invocations. If you set `references` without `compilerOptions.composite = true`, `tsc` will fail, indicating that `composite` needs to be set. When I run `pkgroll` and have `composite` set, I get TS6307 for every file included from `src/index.ts`. rollup-plugin-dts does not handle `composite` (see Swatinem/rollup-plugin-dts#127, which was closed without fix or explanation). I looked at several other related tools (rollup-plugin-typescript2, rollup-plugin-ts, others mentioned in Swatinem/rollup-plugin-dts) and could not get any of them working to build *just* the DTS files (rollup-plugin-typescript2 was the most promising, but I could not get it working in the time that I allotted for this investigation). Going back to rollup-plugin-dts, we find the `compilerOptions` option, and I tried explicitly setting `composite: false`, which allows my type files to build again without errors. I don't think that this is the *correct* fix; ideally, rollup-plugin-dts would be fixed to better handle composite projects *or* would override `composite` at all times. An alternative change, although much more invasive to pkgroll, would be to have pkgroll accept an *alternate* `tsconfig.json` as a parameter: ```console $ pkgroll --tsconfig tsconfig.pkgroll.json ``` In the short term, this has eliminated the build issue that I have been seeing, and it may be sufficient to resolve this until a better fix can be determined in some way, whether by a `--tsconfig` parameter, upstream fixes, or changing to a different bundler plugin for type declaration plugins. This issue can be seen at: https://github.com/halostatue/pkgroll-monorepo-types-issue --- src/utils/get-rollup-configs.ts | 1 + .../packages/one/src/index.ts | 1 + .../fixture-monorepo/packages/one/src/name.ts | 3 ++ .../packages/one/tsconfig.json | 9 +++++ .../packages/two/src/index.ts | 5 +++ .../packages/two/tsconfig.json | 10 +++++ tests/fixture-monorepo/tsconfig.json | 6 +++ tests/specs/builds/output-types.ts | 39 +++++++++++++++++++ 8 files changed, 74 insertions(+) create mode 100644 tests/fixture-monorepo/packages/one/src/index.ts create mode 100644 tests/fixture-monorepo/packages/one/src/name.ts create mode 100644 tests/fixture-monorepo/packages/one/tsconfig.json create mode 100644 tests/fixture-monorepo/packages/two/src/index.ts create mode 100644 tests/fixture-monorepo/packages/two/tsconfig.json create mode 100644 tests/fixture-monorepo/tsconfig.json diff --git a/src/utils/get-rollup-configs.ts b/src/utils/get-rollup-configs.ts index e7b4127..d8db22d 100644 --- a/src/utils/get-rollup-configs.ts +++ b/src/utils/get-rollup-configs.ts @@ -49,6 +49,7 @@ const getConfig = { resolveTypescriptMjsCts(), dts.default({ respectExternal: true, + compilerOptions: { composite: false }, }) as Plugin, ], output: [] as unknown as Output, diff --git a/tests/fixture-monorepo/packages/one/src/index.ts b/tests/fixture-monorepo/packages/one/src/index.ts new file mode 100644 index 0000000..cf0ee25 --- /dev/null +++ b/tests/fixture-monorepo/packages/one/src/index.ts @@ -0,0 +1 @@ +export { Name } from './name.js'; diff --git a/tests/fixture-monorepo/packages/one/src/name.ts b/tests/fixture-monorepo/packages/one/src/name.ts new file mode 100644 index 0000000..c0bacab --- /dev/null +++ b/tests/fixture-monorepo/packages/one/src/name.ts @@ -0,0 +1,3 @@ +declare const name: unique symbol; + +export type Name = string & { [name]: never }; diff --git a/tests/fixture-monorepo/packages/one/tsconfig.json b/tests/fixture-monorepo/packages/one/tsconfig.json new file mode 100644 index 0000000..334ee4e --- /dev/null +++ b/tests/fixture-monorepo/packages/one/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "jsx": "react", + "moduleResolution": "node", + "composite": true, + "outDir": "dist" + }, + "include": ["src/index.ts"] +} diff --git a/tests/fixture-monorepo/packages/two/src/index.ts b/tests/fixture-monorepo/packages/two/src/index.ts new file mode 100644 index 0000000..7fb8a86 --- /dev/null +++ b/tests/fixture-monorepo/packages/two/src/index.ts @@ -0,0 +1,5 @@ +import { Name } from '@org/one'; + +export function sayHello(name: Name) { + console.log('Hello', name); +} diff --git a/tests/fixture-monorepo/packages/two/tsconfig.json b/tests/fixture-monorepo/packages/two/tsconfig.json new file mode 100644 index 0000000..5282a4b --- /dev/null +++ b/tests/fixture-monorepo/packages/two/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "jsx": "react", + "moduleResolution": "node", + "composite": true, + "outDir": "dist" + }, + "include": ["src/index.ts"], + "references": [{ "path": "../one" }] +} diff --git a/tests/fixture-monorepo/tsconfig.json b/tests/fixture-monorepo/tsconfig.json new file mode 100644 index 0000000..e35241c --- /dev/null +++ b/tests/fixture-monorepo/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "moduleResolution": "node" + }, + "resources": [{ "path": "./packages/one" }, { "path": "./packages/two" }] +} diff --git a/tests/specs/builds/output-types.ts b/tests/specs/builds/output-types.ts index aef5aa2..bc212f0 100644 --- a/tests/specs/builds/output-types.ts +++ b/tests/specs/builds/output-types.ts @@ -219,5 +219,44 @@ export default testSuite(({ describe }, nodePath: string) => { const content = await fixture.readFile('dist/dts.d.ts', 'utf8'); expect(content).toMatch('declare const'); }); + + test('handles types in composite monorepos correctly', async ({ onTestFinish }) => { + const fixture = await createFixture('./tests/fixture-monorepo'); + onTestFinish(async () => await fixture.rm()); + + await installTypeScript(fixture.path); + + await fixture.writeJson('package.json', { + workspaces: ['packages/*'], + }); + + await fixture.writeJson('packages/one/package.json', { + name: '@org/one', + type: 'module', + exports: { types: './dist/index.d.mts' }, + }); + + const pkgrollOne = await pkgroll([], { cwd: `${fixture.path}/packages/one`, nodePath }); + expect(pkgrollOne.exitCode).toBe(0); + expect(pkgrollOne.stderr).toBe(''); + + const contentOne = await fixture.readFile('packages/one/dist/index.d.mts', 'utf8'); + expect(contentOne).toMatch('export type { Name };'); + + await fixture.writeJson('packages/two/package.json', { + main: './dist/index.mjs', + type: 'module', + dependencies: { + '@org/one': 'workspace:*', + }, + }); + + const pkgrollTwo = await pkgroll([], { cwd: `${fixture.path}/packages/two`, nodePath }); + expect(pkgrollTwo.exitCode).toBe(0); + expect(pkgrollTwo.stderr).toBe(''); + + const contentTwo = await fixture.readFile('packages/two/dist/index.mjs', 'utf8'); + expect(contentTwo).toMatch('export { sayHello };'); + }); }); });