-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Description
The TypeScript builder's buildFile method fails when processing individual TypeScript files during watch mode, throwing the error:
Cannot use both "outfile" and "outdir"
Additionally, the typescript.outDir configuration option is not respected for single file builds.
Root Causes
Issue 1: Conflicting esbuild options in buildFile method
Location: dist/builders/typescript.js:198-206
The buildFile method passes both outdir and outfile to esbuild, which is not allowed:
const buildOptions = {
entryPoints: [filePath],
outdir: path.dirname(outputPath), // ❌ This line causes the conflict
outfile: outputPath,
format: 'esm',
...this.config.esbuild,
tsconfig: await this.findTsConfig(),
plugins,
};Issue 2: Invalid path transformation in transformOutputPath plugin
Location: dist/builders/typescript.js:170-190
The outfile-transformer plugin returns relative paths instead of absolute paths, causing a secondary error:
Plugin "outfile-transformer" returned a non-absolute path: ./source/js/wf-block-overflow.ts
Issue 3: typescript.outDir not respected
Location: dist/builders/typescript.js:139-150
The getOutputPath method only uses config.output.path and ignores config.typescript.outDir, meaning the TypeScript-specific output directory configuration has no effect.
Steps to Reproduce
- Create a TypeScript file in your source directory (e.g.,
source/ts/example.ts) - Configure ice-build with a TypeScript output directory:
// ice.config.js module.exports = { typescript: { outDir: 'public/js', } }
- Run
ice-build watch - Save the TypeScript file to trigger a rebuild
Expected: File compiles successfully to public/js/example.js
Actual: Build fails with error: Cannot use both "outfile" and "outdir"
Proposed Fixes
Fix 1: Remove outdir from buildFile options
// dist/builders/typescript.js:198-206
const buildOptions = {
entryPoints: [filePath],
outfile: outputPath, // Only use outfile for single file builds
format: 'esm',
...this.config.esbuild,
tsconfig: await this.findTsConfig(),
plugins,
};Fix 2: Simplify transformOutputPath method
The transformOutputPath method is unnecessary for single file builds since the output path is already calculated by getOutputPath. Replace it with a no-op:
// dist/builders/typescript.js:170-174
transformOutputPath(buildOptions) {
// Path transformation handled by getOutputPath
return buildOptions;
}Fix 3: Respect typescript.outDir configuration
// dist/builders/typescript.js:139-154
getOutputPath(filePath) {
const inputFileBaseName = path.basename(filePath, path.extname(filePath));
let filenamePattern = '[name].js';
if (this.config.output?.filenames?.js) {
filenamePattern = this.config.output.filenames.js;
}
const outputFileNameWithSubDir = filenamePattern.replace('[name]', inputFileBaseName);
// Use typescript.outDir if specified, otherwise fall back to this.outputPath
let outputDir = this.outputPath;
if (this.config.typescript?.outDir) {
outputDir = this.config.typescript.outDir;
}
return path.join(outputDir, outputFileNameWithSubDir);
}Environment
- ice-build version: 0.7.0
- Node version: 25.2.0
- Platform: macOS (Darwin)
Impact
This bug prevents TypeScript files from being compiled during watch mode, effectively breaking the development workflow for TypeScript projects using ice-build.
Workaround
Currently, the only workaround is to manually patch the node_modules/@n8d/ice-build/dist/builders/typescript.js file with the fixes described above.