diff --git a/package.json b/package.json index fc4c414..5c8bc18 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ }, "devDependencies": { "@types/node": "^20.14.11", + "@types/react": "^18.3.5", "clean-pkg-json": "^1.2.0", "cleye": "^1.3.2", "execa": "^9.3.0", @@ -70,6 +71,7 @@ "lintroll": "^1.7.1", "manten": "^1.3.0", "outdent": "^0.8.0", + "react": "^18.3.1", "rollup-plugin-dts": "6.1.1", "tsx": "^4.16.2", "type-fest": "^4.22.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc26f97..7313394 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,6 +42,9 @@ importers: '@types/node': specifier: ^20.14.11 version: 20.14.11 + '@types/react': + specifier: ^18.3.5 + version: 18.3.5 clean-pkg-json: specifier: ^1.2.0 version: 1.2.0 @@ -72,6 +75,9 @@ importers: outdent: specifier: ^0.8.0 version: 0.8.0 + react: + specifier: ^18.3.1 + version: 18.3.1 rollup-plugin-dts: specifier: 6.1.1 version: 6.1.1(rollup@4.18.1)(typescript@5.5.3) @@ -699,6 +705,12 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/prop-types@15.7.12': + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + + '@types/react@18.3.5': + resolution: {integrity: sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1006,6 +1018,9 @@ packages: engines: {node: '>=4'} hasBin: true + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -2228,6 +2243,10 @@ packages: react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -3133,6 +3152,13 @@ snapshots: '@types/normalize-package-data@2.4.4': {} + '@types/prop-types@15.7.12': {} + + '@types/react@18.3.5': + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 + '@types/resolve@1.20.2': {} '@types/stack-utils@2.0.1': {} @@ -3482,6 +3508,8 @@ snapshots: cssesc@3.0.0: {} + csstype@3.1.3: {} + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 @@ -4999,6 +5027,10 @@ snapshots: react-is@18.2.0: {} + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 diff --git a/src/utils/get-source-path.ts b/src/utils/get-source-path.ts index 2b50c53..b0dc619 100644 --- a/src/utils/get-source-path.ts +++ b/src/utils/get-source-path.ts @@ -19,12 +19,12 @@ const tryExtensions = async ( }; const extensionMap = { - '.d.ts': ['.d.ts', '.d.mts', '.d.cts', '.ts', '.mts', '.cts'], - '.d.mts': ['.d.mts', '.d.ts', '.d.cts', '.ts', '.mts', '.cts'], - '.d.cts': ['.d.cts', '.d.ts', '.d.mts', '.ts', '.mts', '.cts'], + '.d.ts': ['.d.ts', '.d.mts', '.d.cts', '.ts', '.tsx', '.mts', '.cts'], + '.d.mts': ['.d.mts', '.d.ts', '.d.cts', '.ts', '.tsx', '.mts', '.cts'], + '.d.cts': ['.d.cts', '.d.ts', '.d.mts', '.ts', '.tsx', '.mts', '.cts'], '.js': ['.js', '.ts', '.tsx', '.mts', '.cts'], - '.mjs': ['.mjs', '.js', '.cjs', '.mts', '.cts', '.ts'], - '.cjs': ['.cjs', '.js', '.mjs', '.mts', '.cts', '.ts'], + '.mjs': ['.mjs', '.js', '.cjs', '.mts', '.cts', '.ts', '.tsx'], + '.cjs': ['.cjs', '.js', '.mjs', '.mts', '.cts', '.ts', '.tsx'], } as const; const distExtensions = Object.keys(extensionMap) as (keyof typeof extensionMap)[]; diff --git a/tests/fixtures.ts b/tests/fixtures.ts index 8b38387..af6dbbc 100644 --- a/tests/fixtures.ts +++ b/tests/fixtures.ts @@ -6,14 +6,18 @@ import type { PackageJson, TsConfigJson } from 'type-fest'; export const createPackageJson = (packageJson: PackageJson) => JSON.stringify(packageJson); export const createTsconfigJson = (tsconfigJson: TsConfigJson) => JSON.stringify(tsconfigJson); -const typeScriptPath = path.resolve('node_modules/typescript'); - export const installTypeScript: FileTree = { - 'node_modules/typescript': ({ symlink }) => symlink(typeScriptPath, 'dir'), + 'node_modules/typescript': ({ symlink }) => symlink(path.resolve('node_modules/typescript'), 'dir'), +}; + +export const installReact: FileTree = { + 'node_modules/react': ({ symlink }) => symlink(path.resolve('node_modules/react'), 'dir'), + 'node_modules/@types/react': ({ symlink }) => symlink(path.resolve('node_modules/@types/react'), 'dir'), }; type Options = { installTypeScript?: boolean; + installReact?: boolean; }; export const fixtureFiles = { @@ -159,20 +163,13 @@ export const fixtureFiles = { `, }; -export const packageFixture = ( - options: Options = {}, -): FileTree => ({ +export const packageFixture = (options: Options = {}): FileTree => ({ src: fixtureFiles, - ...( - options.installTypeScript - ? installTypeScript - : {} - ), + ...(options.installTypeScript ? installTypeScript : {}), + ...(options.installReact ? installReact : {}), }); -export const fixtureDependencyExportsMap = ( - entryFile: string, -): FileTree => ({ +export const fixtureDependencyExportsMap = (entryFile: string): FileTree => ({ 'package.json': createPackageJson({ main: entryFile, }), diff --git a/tests/specs/builds/output-commonjs.ts b/tests/specs/builds/output-commonjs.ts index 5826e2b..bdd11d6 100644 --- a/tests/specs/builds/output-commonjs.ts +++ b/tests/specs/builds/output-commonjs.ts @@ -1,7 +1,7 @@ import { testSuite, expect } from 'manten'; import { createFixture } from 'fs-fixture'; import { pkgroll } from '../../utils.js'; -import { packageFixture, createPackageJson } from '../../fixtures.js'; +import { packageFixture, createPackageJson, createTsconfigJson } from '../../fixtures.js'; export default testSuite(({ describe }, nodePath: string) => { describe('output: commonjs', ({ test }) => { @@ -126,6 +126,36 @@ export default testSuite(({ describe }, nodePath: string) => { expect(content).toMatch('exports.sayHello ='); }); + test('{ type: commonjs, field: component, srcExt: mjs, distExt: cjs }', async () => { + await using fixture = await createFixture({ + ...packageFixture({ installReact: true }), + 'package.json': createPackageJson({ + main: './dist/component.cjs', + peerDependencies: { + react: '*', + }, + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + jsx: 'react-jsx', + }, + }), + }); + + const pkgrollProcess = await pkgroll([], { + cwd: fixture.path, + nodePath, + }); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + const content = await fixture.readFile('dist/component.cjs', 'utf8'); + expect(content).toMatch(`require('react/jsx-runtime')`); + expect(content).toMatch('const Component = () => /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Hello World" })'); + expect(content).toMatch('exports.Component = Component'); + }); + test('nested directory', async () => { await using fixture = await createFixture({ ...packageFixture(), diff --git a/tests/specs/builds/output-module.ts b/tests/specs/builds/output-module.ts index 582b9a8..21f4d99 100644 --- a/tests/specs/builds/output-module.ts +++ b/tests/specs/builds/output-module.ts @@ -1,7 +1,7 @@ import { testSuite, expect } from 'manten'; import { createFixture } from 'fs-fixture'; import { pkgroll } from '../../utils.js'; -import { packageFixture, createPackageJson } from '../../fixtures.js'; +import { packageFixture, createPackageJson, createTsconfigJson } from '../../fixtures.js'; export default testSuite(({ describe }, nodePath: string) => { describe('output: module', ({ test }) => { @@ -86,6 +86,36 @@ export default testSuite(({ describe }, nodePath: string) => { expect(content).toMatch('export { cjs$1 as default }'); }); + test('{ type: commonjs, field: component, srcExt: tsx, distExt: mjs }', async () => { + await using fixture = await createFixture({ + ...packageFixture({ installReact: true }), + 'package.json': createPackageJson({ + main: './dist/component.mjs', + peerDependencies: { + react: '*', + }, + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + jsx: 'react-jsx', + }, + }), + }); + + const pkgrollProcess = await pkgroll([], { + cwd: fixture.path, + nodePath, + }); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + const content = await fixture.readFile('dist/component.mjs', 'utf8'); + expect(content).toMatch(`import { jsx } from 'react/jsx-runtime'`); + expect(content).toMatch('const Component = () => /* @__PURE__ */ jsx("div", { children: "Hello World" })'); + expect(content).toMatch('export { Component }'); + }); + test('{ type: commonjs, field: main, srcExt: mts, distExt: mjs }', async () => { await using fixture = await createFixture({ ...packageFixture(), diff --git a/tests/specs/builds/output-types.ts b/tests/specs/builds/output-types.ts index 314e6c0..11a9e95 100644 --- a/tests/specs/builds/output-types.ts +++ b/tests/specs/builds/output-types.ts @@ -60,6 +60,105 @@ export default testSuite(({ describe }, nodePath: string) => { expect(content).toMatch('declare function'); }); + test('{ srcExt: tsx, distExt: d.ts }', async () => { + await using fixture = await createFixture({ + ...packageFixture({ + installTypeScript: true, + installReact: true, + }), + 'package.json': createPackageJson({ + types: './dist/component.d.ts', + peerDependencies: { + react: '*', + }, + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + jsx: 'react-jsx', + }, + }), + }); + + const pkgrollProcess = await pkgroll([], { + cwd: fixture.path, + nodePath, + }); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + const content = await fixture.readFile('dist/component.d.ts', 'utf8'); + expect(content).toMatch(`import * as react_jsx_runtime from 'react/jsx-runtime'`); + expect(content).toMatch('declare const Component: () => react_jsx_runtime.JSX.Element'); + expect(content).toMatch('export { Component }'); + }); + + test('{ srcExt: tsx, distExt: d.mts }', async () => { + await using fixture = await createFixture({ + ...packageFixture({ + installTypeScript: true, + installReact: true, + }), + 'package.json': createPackageJson({ + types: './dist/component.d.mts', + peerDependencies: { + react: '*', + }, + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + jsx: 'react-jsx', + }, + }), + }); + + const pkgrollProcess = await pkgroll([], { + cwd: fixture.path, + nodePath, + }); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + const content = await fixture.readFile('dist/component.d.mts', 'utf8'); + expect(content).toMatch(`import * as react_jsx_runtime from 'react/jsx-runtime'`); + expect(content).toMatch('declare const Component: () => react_jsx_runtime.JSX.Element'); + expect(content).toMatch('export { Component }'); + }); + + test('{ srcExt: tsx, distExt: d.cts }', async () => { + await using fixture = await createFixture({ + ...packageFixture({ + installTypeScript: true, + installReact: true, + }), + 'package.json': createPackageJson({ + types: './dist/component.d.cts', + peerDependencies: { + react: '*', + }, + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + jsx: 'react-jsx', + }, + }), + }); + + const pkgrollProcess = await pkgroll([], { + cwd: fixture.path, + nodePath, + }); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + const content = await fixture.readFile('dist/component.d.cts', 'utf8'); + expect(content).toMatch(`import * as react_jsx_runtime from 'react/jsx-runtime'`); + expect(content).toMatch('declare const Component: () => react_jsx_runtime.JSX.Element'); + expect(content).toMatch('export { Component }'); + }); + test('{ srcExt: .mts, distExt: d.cts }', async () => { await using fixture = await createFixture({ ...packageFixture({ installTypeScript: true }),