Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: basic implementation of dts generation #42

Merged
merged 1 commit into from
Aug 1, 2024
Merged
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
4 changes: 2 additions & 2 deletions e2e/cases/alias/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('source.alias', async () => {
const fixturePath = __dirname;
const { entries } = await buildAndGetJsResults(fixturePath);
const { entries } = await buildAndGetResults(fixturePath);

expect(entries.esm).toContain('hello world');
expect(entries.cjs).toContain('hello world');
Expand Down
6 changes: 3 additions & 3 deletions e2e/cases/autoExtension/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { extname, join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('autoExtension generate .mjs in build artifacts with esm format when type is commonjs', async () => {
const fixturePath = join(__dirname, 'type-commonjs');
const { entryFiles } = await buildAndGetJsResults(fixturePath);
const { entryFiles } = await buildAndGetResults(fixturePath);
expect(extname(entryFiles.esm!)).toEqual('.mjs');
expect(extname(entryFiles.cjs!)).toEqual('.js');
});

test('autoExtension generate .cjs in build artifacts with cjs format when type is module', async () => {
const fixturePath = join(__dirname, 'type-module');
const { entryFiles } = await buildAndGetJsResults(fixturePath);
const { entryFiles } = await buildAndGetResults(fixturePath);
expect(extname(entryFiles.esm!)).toEqual('.js');
expect(extname(entryFiles.cjs!)).toEqual('.cjs');
});
4 changes: 2 additions & 2 deletions e2e/cases/bundle-false/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('bundle: false', async () => {
const fixturePath = join(__dirname, 'basic');
const { files } = await buildAndGetJsResults(fixturePath);
const { files } = await buildAndGetResults(fixturePath);

// TODO: record file paths with inline snapshot
// need to add path serialization
Expand Down
4 changes: 2 additions & 2 deletions e2e/cases/define/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('source.define', async () => {
const fixturePath = __dirname;
const { entries } = await buildAndGetJsResults(fixturePath);
const { entries } = await buildAndGetResults(fixturePath);

expect(entries.esm).not.toContain('console.info(VERSION)');
expect(entries.esm).toContain('1.0.0');
Expand Down
44 changes: 44 additions & 0 deletions e2e/cases/dts/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`dts when bundle: false 1`] = `
{
"./dist/esm/index.d.ts": "export * from './utils/numbers';
export * from './utils/strings';
export * from './sum';
",
"./dist/esm/sum.d.ts": "export declare const numSum: number;
export declare const strSum: string;
",
"./dist/esm/utils/numbers.d.ts": "export declare const num1 = 1;
export declare const num2 = 2;
export declare const num3 = 3;
",
"./dist/esm/utils/strings.d.ts": "export declare const str1 = "str1";
export declare const str2 = "str2";
export declare const str3 = "str3";
",
}
`;

exports[`dts when bundle: true 1`] = `
{
"esm": "export declare const num1 = 1;

export declare const num2 = 2;

export declare const num3 = 3;

export declare const numSum: number;

export declare const str1 = "str1";

export declare const str2 = "str2";

export declare const str3 = "str3";

export declare const strSum: string;

export { }
",
}
`;
21 changes: 21 additions & 0 deletions e2e/cases/dts/bundle-false/rslib.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from '@rslib/core';
import { generateBundleCjsConfig, generateBundleEsmConfig } from '#shared';

export default defineConfig({
lib: [
generateBundleEsmConfig(__dirname, {
bundle: false,
dts: {
bundle: false,
},
}),
generateBundleCjsConfig(__dirname, {
bundle: false,
}),
],
source: {
entry: {
main: ['./src/**'],
},
},
});
3 changes: 3 additions & 0 deletions e2e/cases/dts/bundle-false/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './utils/numbers';
export * from './utils/strings';
export * from './sum';
5 changes: 5 additions & 0 deletions e2e/cases/dts/bundle-false/src/sum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { num1, num2, num3 } from './utils/numbers';
import { str1, str2, str3 } from './utils/strings';

export const numSum = num1 + num2 + num3;
export const strSum = str1 + str2 + str3;
3 changes: 3 additions & 0 deletions e2e/cases/dts/bundle-false/src/utils/numbers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const num1 = 1;
export const num2 = 2;
export const num3 = 3;
3 changes: 3 additions & 0 deletions e2e/cases/dts/bundle-false/src/utils/strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const str1 = 'str1';
export const str2 = 'str2';
export const str3 = 'str3';
7 changes: 7 additions & 0 deletions e2e/cases/dts/bundle-false/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@rslib/tsconfig/base",
"compilerOptions": {
"baseUrl": "./"
},
"include": ["src"]
}
6 changes: 6 additions & 0 deletions e2e/cases/dts/bundle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "dts-bundle-test",
"version": "1.0.0",
"private": true,
"type": "module"
}
21 changes: 21 additions & 0 deletions e2e/cases/dts/bundle/rslib.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from '@rslib/core';
import {
generateBundleCjsConfig,
generateBundleEsmConfig,
} from '../../../scripts/shared';

export default defineConfig({
lib: [
generateBundleEsmConfig(__dirname, {
dts: {
bundle: true,
},
}),
generateBundleCjsConfig(__dirname),
],
source: {
entry: {
main: './src/index.ts',
},
},
});
3 changes: 3 additions & 0 deletions e2e/cases/dts/bundle/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './utils/numbers';
export * from './utils/strings';
export * from './sum';
5 changes: 5 additions & 0 deletions e2e/cases/dts/bundle/src/sum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { num1, num2, num3 } from './utils/numbers';
import { str1, str2, str3 } from './utils/strings';

export const numSum = num1 + num2 + num3;
export const strSum = str1 + str2 + str3;
3 changes: 3 additions & 0 deletions e2e/cases/dts/bundle/src/utils/numbers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const num1 = 1;
export const num2 = 2;
export const num3 = 3;
3 changes: 3 additions & 0 deletions e2e/cases/dts/bundle/src/utils/strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const str1 = 'str1';
export const str2 = 'str2';
export const str3 = 'str3';
7 changes: 7 additions & 0 deletions e2e/cases/dts/bundle/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@rslib/tsconfig/base",
"compilerOptions": {
"baseUrl": "./"
},
"include": ["src"]
}
20 changes: 20 additions & 0 deletions e2e/cases/dts/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetResults } from '#shared';

test('dts when bundle: false', async () => {
const fixturePath = join(__dirname, 'bundle-false');
const { files, contents } = await buildAndGetResults(fixturePath, 'dts');

expect(files.esm?.length).toBe(4);
expect(files.esm?.[0]!.endsWith('.d.ts')).toEqual(true);
Timeless0911 marked this conversation as resolved.
Show resolved Hide resolved
expect(contents.esm).toMatchSnapshot();
});

test('dts when bundle: true', async () => {
const fixturePath = join(__dirname, 'bundle');
const { entryFiles, entries } = await buildAndGetResults(fixturePath, 'dts');

expect(entryFiles.esm!.endsWith('index.d.ts')).toEqual(true);
expect(entries).toMatchSnapshot();
});
4 changes: 2 additions & 2 deletions e2e/cases/externals/browser/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('should fail to build when `output.target` is not "node"', async () => {
const fixturePath = join(__dirname);
const build = buildAndGetJsResults(fixturePath);
const build = buildAndGetResults(fixturePath);
await expect(build).rejects.toThrowError('Rspack build failed!');
});
4 changes: 2 additions & 2 deletions e2e/cases/externals/node/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('auto externalize Node.js built-in modules when `output.target` is "node"', async () => {
const fixturePath = join(__dirname);
const { entries } = await buildAndGetJsResults(fixturePath);
const { entries } = await buildAndGetResults(fixturePath);

for (const external of [
'import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs"',
Expand Down
4 changes: 2 additions & 2 deletions e2e/cases/syntax/config/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('should downgrade class private method by default', async () => {
const fixturePath = __dirname;
const { entries } = await buildAndGetJsResults(fixturePath);
const { entries } = await buildAndGetResults(fixturePath);

expect(entries.esm).toMatchSnapshot();
expect(entries.esm).not.toContain('#bar');
Expand Down
4 changes: 2 additions & 2 deletions e2e/cases/syntax/default/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';
import { buildAndGetResults } from '#shared';

test('should downgrade class private method by default', async () => {
const fixturePath = __dirname;
const { entries } = await buildAndGetJsResults(fixturePath);
const { entries } = await buildAndGetResults(fixturePath);

expect(entries.esm).toMatchSnapshot();
expect(entries.esm).toContain('#bar');
Expand Down
2 changes: 1 addition & 1 deletion e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"devDependencies": {
"@playwright/test": "1.43.1",
"@rsbuild/core": "1.0.1-beta.6",
"@rsbuild/core": "1.0.1-beta.8",
"@rslib/core": "workspace:*",
"@rslib/tsconfig": "workspace:*",
"@types/fs-extra": "^11.0.4",
Expand Down
56 changes: 43 additions & 13 deletions e2e/scripts/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,58 @@ export function generateBundleCjsConfig(
return mergeConfig(cjsBasicConfig, config)!;
}

export async function getJsResults(rslibConfig: RslibConfig) {
export async function getResults(
rslibConfig: RslibConfig,
fixturePath: string,
type: 'js' | 'dts',
) {
const files: Record<string, string[]> = {};
const contents: Record<string, Record<string, string>> = {};
const entries: Record<string, string> = {};
const entryFiles: Record<string, string> = {};

for (const libConfig of rslibConfig.lib) {
const content = await globContentJSON(libConfig?.output?.distPath?.root!, {
let globFolder = '';
if (type === 'js') {
globFolder = libConfig?.output?.distPath?.root!;
} else if (type === 'dts' && libConfig.dts !== false) {
globFolder =
libConfig.dts?.distPath! ?? libConfig?.output?.distPath?.root!;
}

if (!globFolder) continue;

const regex = type === 'dts' ? /\.d.(ts|cts|mts)$/ : /\.(js|cjs|mjs)$/;

const rawContent = await globContentJSON(globFolder, {
absolute: true,
ignore: ['/**/*.map'],
});

const jsFiles = Object.keys(content).filter((file) =>
/\.(js|cjs|mjs)$/.test(file),
);
const content: Record<string, string> = {};

for (const key of Object.keys(rawContent)) {
const newKey = key.replace(fixturePath, '.');
content[newKey] = rawContent[key]!;
}

const fileSet = Object.keys(content).filter((file) => regex.test(file));
const filterContent: Record<string, string> = {};
for (const key of fileSet) {
if (content[key]) {
filterContent[key] = content[key];
}
}

if (jsFiles.length) {
files[libConfig.format!] = jsFiles;
contents[libConfig.format!] = content;
if (fileSet.length) {
files[libConfig.format!] = fileSet;
contents[libConfig.format!] = filterContent;
}

// Only applied in bundle mode, a shortcut to get single entry result
if (libConfig.bundle !== false && jsFiles.length === 1) {
entries[libConfig.format!] = Object.values(content)[0]!;
entryFiles[libConfig.format!] = jsFiles[0]!;
if (libConfig.bundle !== false && fileSet.length === 1) {
entries[libConfig.format!] = content[fileSet[0]!]!;
entryFiles[libConfig.format!] = fileSet[0]!;
}
}

Expand All @@ -73,11 +100,14 @@ export async function getJsResults(rslibConfig: RslibConfig) {
};
}

export const buildAndGetJsResults = async (fixturePath: string) => {
export const buildAndGetResults = async (
fixturePath: string,
type: 'js' | 'dts' = 'js',
) => {
const rslibConfig = await loadConfig(join(fixturePath, 'rslib.config.ts'));
process.chdir(fixturePath);
await build(rslibConfig);
const results = await getJsResults(rslibConfig);
const results = await getResults(rslibConfig, fixturePath, type);
return {
contents: results.contents,
files: results.files,
Expand Down
7 changes: 6 additions & 1 deletion packages/core/modern.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { defineConfig, moduleTools } from '@modern-js/module-tools';
import prebundleConfig from './prebundle.config.mjs';

const externals = ['@rsbuild/core', /[\\/]compiled[\\/]/, /node:/];
const externals = [
'@rsbuild/core',
/[\\/]compiled[\\/]/,
/node:/,
'typescript',
];
const define = {
RSLIB_VERSION: require('./package.json').version,
};
Expand Down
Loading
Loading