Skip to content

Commit 7a6f343

Browse files
committed
feat: add oxc-transform as optional declaration generator
1 parent 073a6cb commit 7a6f343

File tree

9 files changed

+404
-283
lines changed

9 files changed

+404
-283
lines changed

.changeset/friendly-radios-walk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@ice/pkg': minor
3+
---
4+
5+
feat: add oxc-transform as optional declaration generator

examples/react-component/build.config.mts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default defineConfig({
99
formats: ['esm', 'es2017', 'cjs'],
1010
},
1111
jsxRuntime: 'classic',
12+
declaration: {
13+
generator: 'oxc'
14+
},
1215
sourceMaps: false,
1316
bundle: {
1417
formats: ['esm', 'es2017'],

packages/pkg/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"gzip-size": "^7.0.0",
6262
"lodash.merge": "^4.6.2",
6363
"magic-string": "^0.25.7",
64+
"oxc-transform": "^0.35.0",
6465
"picocolors": "^1.0.0",
6566
"postcss": "^8.4.31",
6667
"postcss-plugin-rpx2vw": "^1.0.0",
@@ -69,7 +70,7 @@
6970
"rollup-plugin-visualizer": "^5.12.0",
7071
"semver": "^7.5.2",
7172
"tsc-alias": "^1.8.2",
72-
"typescript": "^4.9.5"
73+
"typescript": "^5.6.0"
7374
},
7475
"devDependencies": {
7576
"@types/babel__core": "^7.1.20",

packages/pkg/src/helpers/dts.ts

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export interface DtsCompileOptions {
4343
alias: TaskConfig['alias'];
4444
rootDir: string;
4545
outputDir: string;
46+
usingOxc: boolean;
4647
}
4748

4849
function formatAliasToTSPathsConfig(alias: TaskConfig['alias']) {
@@ -116,7 +117,7 @@ async function getProjectTSConfig(rootDir: string): Promise<ts.ParsedCommandLine
116117
};
117118
}
118119

119-
export async function dtsCompile({ files, rootDir, outputDir, alias }: DtsCompileOptions): Promise<DtsInputFile[]> {
120+
export async function dtsCompile({ files, rootDir, outputDir, alias, usingOxc }: DtsCompileOptions): Promise<DtsInputFile[]> {
120121
if (!files.length) {
121122
return [];
122123
}
@@ -132,18 +133,53 @@ export async function dtsCompile({ files, rootDir, outputDir, alias }: DtsCompil
132133
dtsPath: normalizePath(dtsPath),
133134
}));
134135

136+
const compileFunction = usingOxc ? compileFromOxc : compileFromTsc;
137+
const dtsFiles = await compileFunction(_files, tsConfig)
138+
139+
if (!Object.keys(alias).length) {
140+
// no alias config
141+
return _files.map((file) => ({
142+
...file,
143+
dtsContent: dtsFiles[file.dtsPath],
144+
}));
145+
}
146+
147+
// We use tsc-alias to resolve d.ts alias.
148+
// Reason: https://github.com/microsoft/TypeScript/issues/30952#issuecomment-1114225407
149+
const tsConfigLocalPath = path.join(rootDir, 'node_modules/.cache/ice-pkg/tsconfig.json');
150+
await fse.ensureFile(tsConfigLocalPath);
151+
await fse.writeJSON(tsConfigLocalPath, {
152+
...tsConfig,
153+
compilerOptions: tsConfig.options,
154+
}, { spaces: 2 });
155+
156+
const runFile = await prepareSingleFileReplaceTscAliasPaths({
157+
configFile: tsConfigLocalPath,
158+
outDir: outputDir,
159+
});
160+
161+
const result = _files.map((file) => ({
162+
...file,
163+
dtsContent: dtsFiles[file.dtsPath] ? runFile({ fileContents: dtsFiles[file.dtsPath], filePath: file.dtsPath }) : '',
164+
}));
165+
166+
return result;
167+
}
168+
169+
async function compileFromTsc(files: DtsInputFile[], tsConfig: ts.ParsedCommandLine): Promise<Record<string, string>> {
135170
// In order to only include the update files instead of all the files in the watch mode.
136171
function getProgramRootNames(originalFilenames: string[]) {
137172
// Should include all the resolved .d.ts file to avoid dts generate error:
138173
// TS4025: Exported variable '<name>' has or is using private name '<name>'.
139174
const dtsFilenames = originalFilenames.filter((filename) => filename.endsWith('.d.ts'));
140-
const needCompileFileNames = _files.map(({ filePath }) => filePath);
175+
const needCompileFileNames = files.map(({ filePath }) => filePath);
141176
return [...needCompileFileNames, ...dtsFilenames];
142177
}
143178

144-
const dtsFiles = {};
145179
const host = ts.createCompilerHost(tsConfig.options);
146180

181+
const dtsFiles: Record<string, string> = {};
182+
147183
host.writeFile = (fileName, contents) => {
148184
dtsFiles[fileName] = contents;
149185
};
@@ -171,32 +207,23 @@ export async function dtsCompile({ files, rootDir, outputDir, alias }: DtsCompil
171207
});
172208
}
173209

174-
if (!Object.keys(alias).length) {
175-
// no alias config
176-
return _files.map((file) => ({
177-
...file,
178-
dtsContent: dtsFiles[file.dtsPath],
179-
}));
180-
}
181-
182-
// We use tsc-alias to resolve d.ts alias.
183-
// Reason: https://github.com/microsoft/TypeScript/issues/30952#issuecomment-1114225407
184-
const tsConfigLocalPath = path.join(rootDir, 'node_modules/.cache/ice-pkg/tsconfig.json');
185-
await fse.ensureFile(tsConfigLocalPath);
186-
await fse.writeJSON(tsConfigLocalPath, {
187-
...tsConfig,
188-
compilerOptions: tsConfig.options,
189-
}, { spaces: 2 });
210+
return dtsFiles
211+
}
190212

191-
const runFile = await prepareSingleFileReplaceTscAliasPaths({
192-
configFile: tsConfigLocalPath,
193-
outDir: outputDir,
194-
});
213+
async function compileFromOxc(absFiles: DtsInputFile[], tsConfig: ts.ParsedCommandLine): Promise<Record<string, string>> {
214+
if (!tsConfig.options.isolatedDeclarations) {
215+
consola.warn(`Enable isolatedDeclarations in tsconfig.json for correct .d.ts file generation`)
216+
}
217+
const oxc = await import('oxc-transform');
218+
const dtsFiles: Record<string, string> = {};
219+
for (const file of absFiles) {
220+
const fileContent = fse.readFileSync(file.filePath, 'utf-8');
221+
const { code } = oxc.isolatedDeclaration(file.filePath, fileContent, {
222+
sourcemap: false,
223+
});
195224

196-
const result = _files.map((file) => ({
197-
...file,
198-
dtsContent: dtsFiles[file.dtsPath] ? runFile({ fileContents: dtsFiles[file.dtsPath], filePath: file.dtsPath }) : '',
199-
}));
225+
dtsFiles[file.dtsPath] = code;
226+
}
200227

201-
return result;
228+
return dtsFiles
202229
}

packages/pkg/src/tasks/declaration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class DeclarationRunner extends Runner<OutputResult> {
5656
rootDir: context.buildContext.rootDir,
5757
outputDir: buildConfig.outputDir,
5858
alias: buildConfig.alias,
59+
usingOxc: buildConfig.generator === 'oxc',
5960
}]);
6061

6162
await worker.terminate();

packages/pkg/src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ export interface DeclarationUserConfig {
112112
* @default 'multi'
113113
*/
114114
outputMode?: 'multi' | 'unique';
115+
116+
/**
117+
* The generator to generate .d.ts file
118+
* - `'tsc'` use typescript
119+
* - `'oxc'` use oxc-transform to generate isolated declaration
120+
* @default 'tsc'
121+
*/
122+
generator?: 'tsc' | 'oxc';
115123
}
116124

117125
export interface UserConfig {

0 commit comments

Comments
 (0)