From dea56be32d17d208c5d9456c6de61d93a1606b0d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 27 Aug 2020 13:26:20 -0500 Subject: [PATCH] fix(dist): ensure src dts files not emitted still get shipped in dist Closes #1797 --- src/compiler/transpile/run-program.ts | 38 +++++++++++++++++--- test/end-to-end/src/app-root/app-root.tsx | 3 +- test/end-to-end/src/app-root/interfaces.d.ts | 1 + test/end-to-end/test-end-to-end-dist.js | 2 ++ 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 test/end-to-end/src/app-root/interfaces.d.ts diff --git a/src/compiler/transpile/run-program.ts b/src/compiler/transpile/run-program.ts index 88a2f1c5ac6..a2e2343808c 100644 --- a/src/compiler/transpile/run-program.ts +++ b/src/compiler/transpile/run-program.ts @@ -1,5 +1,5 @@ import type * as d from '../../declarations'; -import { basename, join } from 'path'; +import { basename, join, relative } from 'path'; import { convertDecoratorsToStatic } from '../transformers/decorators-to-static/convert-decorators'; import { generateAppTypes } from '../types/generate-app-types'; import { getComponentsFromModules, isOutputTargetDistTypes } from '../output-targets/output-utils'; @@ -11,7 +11,12 @@ import { updateModule } from '../transformers/static-to-meta/parse-static'; import { updateStencilTypesImports } from '../types/stencil-types'; import { validateTranspiledComponents } from './validate-components'; -export const runTsProgram = async (config: d.Config, compilerCtx: d.CompilerCtx, buildCtx: d.BuildCtx, tsBuilder: ts.BuilderProgram) => { +export const runTsProgram = async ( + config: d.Config, + compilerCtx: d.CompilerCtx, + buildCtx: d.BuildCtx, + tsBuilder: ts.BuilderProgram, +) => { const tsSyntactic = loadTypeScriptDiagnostics(tsBuilder.getSyntacticDiagnostics()); const tsGlobal = loadTypeScriptDiagnostics(tsBuilder.getGlobalDiagnostics()); const tsOptions = loadTypeScriptDiagnostics(tsBuilder.getOptionsDiagnostics()); @@ -27,12 +32,15 @@ export const runTsProgram = async (config: d.Config, compilerCtx: d.CompilerCtx, const tsTypeChecker = tsProgram.getTypeChecker(); const typesOutputTarget = config.outputTargets.filter(isOutputTargetDistTypes); + const emittedDts: string[] = []; const emitCallback: ts.WriteFileCallback = (emitFilePath, data, _w, _e, tsSourceFiles) => { if (emitFilePath.endsWith('.js')) { updateModule(config, compilerCtx, buildCtx, tsSourceFiles[0], data, emitFilePath, tsTypeChecker, null); } else if (emitFilePath.endsWith('.d.ts')) { - const relativeEmitFilepath = getRelativeDts(config, tsSourceFiles[0].fileName, emitFilePath); + const srcDtsPath = normalizePath(tsSourceFiles[0].fileName); + const relativeEmitFilepath = getRelativeDts(config, srcDtsPath, emitFilePath); + emittedDts.push(srcDtsPath); typesOutputTarget.forEach(o => { const distPath = join(o.typesDir, relativeEmitFilepath); data = updateStencilTypesImports(o.typesDir, distPath, data); @@ -67,6 +75,29 @@ export const runTsProgram = async (config: d.Config, compilerCtx: d.CompilerCtx, return true; } + if (typesOutputTarget.length > 0) { + // copy src dts files that do not get emitted by the compiler + // but we still want to ship them in the dist directory + const srcRootDtsFiles = tsProgram + .getRootFileNames() + .filter(f => f.endsWith('.d.ts') && !f.endsWith('components.d.ts')) + .map(normalizePath) + .filter(f => !emittedDts.includes(f)) + .map(srcRootDtsFilePath => { + const relativeEmitFilepath = relative(config.srcDir, srcRootDtsFilePath); + return Promise.all( + typesOutputTarget.map(async o => { + const distPath = join(o.typesDir, relativeEmitFilepath); + let dtsContent = await compilerCtx.fs.readFile(srcRootDtsFilePath); + dtsContent = updateStencilTypesImports(o.typesDir, distPath, dtsContent); + await compilerCtx.fs.writeFile(distPath, dtsContent); + }), + ); + }); + + await Promise.all(srcRootDtsFiles); + } + if (config.validateTypes) { const tsSemantic = loadTypeScriptDiagnostics(tsBuilder.getSemanticDiagnostics()); if (config.devMode) { @@ -85,7 +116,6 @@ export const runTsProgram = async (config: d.Config, compilerCtx: d.CompilerCtx, const getRelativeDts = (config: d.Config, srcPath: string, emitDtsPath: string) => { const parts: string[] = []; - srcPath = normalizePath(srcPath); for (let i = 0; i < 30; i++) { if (config.srcDir === srcPath) { break; diff --git a/test/end-to-end/src/app-root/app-root.tsx b/test/end-to-end/src/app-root/app-root.tsx index e79daf87e63..e464fdf4351 100644 --- a/test/end-to-end/src/app-root/app-root.tsx +++ b/test/end-to-end/src/app-root/app-root.tsx @@ -3,6 +3,7 @@ import _ from 'lodash'; import _es from 'lodash-es'; import videojs from 'video.js'; import { css } from 'linaria'; +import { MeString } from './interfaces'; const linariaCss = css` background-color: rgba(0, 0, 255, 0.1); @@ -30,7 +31,7 @@ function format(target: any, propertyKey: string) { export class AppRoot { @format something = '12'; @State() first: string; - @State() last: string; + @State() last: MeString; componentWillLoad() { const url = new URL(window.location.href); diff --git a/test/end-to-end/src/app-root/interfaces.d.ts b/test/end-to-end/src/app-root/interfaces.d.ts new file mode 100644 index 00000000000..ace11a4d13b --- /dev/null +++ b/test/end-to-end/src/app-root/interfaces.d.ts @@ -0,0 +1 @@ +export type MeString = string; diff --git a/test/end-to-end/test-end-to-end-dist.js b/test/end-to-end/test-end-to-end-dist.js index 24a78dafee1..c5158cc7f02 100644 --- a/test/end-to-end/test-end-to-end-dist.js +++ b/test/end-to-end/test-end-to-end-dist.js @@ -26,6 +26,8 @@ JSON.parse(fs.readFileSync(path.join(collectionDir, 'collection-manifest.json'), const typesDir = path.join(distDir, 'types'); fs.accessSync(path.join(typesDir, 'components.d.ts')); fs.accessSync(path.join(typesDir, 'stencil-public-runtime.d.ts')); +fs.accessSync(path.join(typesDir, 'app-root', 'app-root.d.ts')); +fs.accessSync(path.join(typesDir, 'app-root', 'interfaces.d.ts')); fs.accessSync(path.join(typesDir, 'car-list', 'car-data.d.ts')); fs.accessSync(path.join(typesDir, 'car-list', 'car-list.d.ts'));