/
run-program.ts
130 lines (113 loc) · 5.01 KB
/
run-program.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import type * as d from '../../declarations';
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';
import { loadTypeScriptDiagnostics, normalizePath } from '@utils';
import { resolveComponentDependencies } from '../entries/resolve-component-dependencies';
import type ts from 'typescript';
import { updateComponentBuildConditionals } from '../app-core/app-data';
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,
) => {
const tsSyntactic = loadTypeScriptDiagnostics(tsBuilder.getSyntacticDiagnostics());
const tsGlobal = loadTypeScriptDiagnostics(tsBuilder.getGlobalDiagnostics());
const tsOptions = loadTypeScriptDiagnostics(tsBuilder.getOptionsDiagnostics());
buildCtx.diagnostics.push(...tsSyntactic);
buildCtx.diagnostics.push(...tsGlobal);
buildCtx.diagnostics.push(...tsOptions);
if (buildCtx.hasError) {
return false;
}
const tsProgram = tsBuilder.getProgram();
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 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);
compilerCtx.fs.writeFile(distPath, data);
});
}
};
// Emit files that changed
tsBuilder.emit(undefined, emitCallback, undefined, false, {
before: [convertDecoratorsToStatic(config, buildCtx.diagnostics, tsTypeChecker)],
});
const changedmodules = Array.from(compilerCtx.changedModules.keys());
buildCtx.debug('Transpiled modules: ' + JSON.stringify(changedmodules, null, '\n'));
// Finalize components metadata
buildCtx.moduleFiles = Array.from(compilerCtx.moduleMap.values());
buildCtx.components = getComponentsFromModules(buildCtx.moduleFiles);
updateComponentBuildConditionals(compilerCtx.moduleMap, buildCtx.components);
resolveComponentDependencies(buildCtx.components);
validateTranspiledComponents(config, buildCtx);
if (buildCtx.hasError) {
return false;
}
// create the components.d.ts file and write to disk
const hasTypesChanged = await generateAppTypes(config, compilerCtx, buildCtx, 'src');
if (hasTypesChanged) {
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) {
tsSemantic.forEach(semanticDiagnostic => {
// Unused variable errors become warnings in dev mode
if (semanticDiagnostic.code === '6133' || semanticDiagnostic.code === '6192') {
semanticDiagnostic.level = 'warn';
}
});
}
buildCtx.diagnostics.push(...tsSemantic);
}
return false;
};
const getRelativeDts = (config: d.Config, srcPath: string, emitDtsPath: string) => {
const parts: string[] = [];
for (let i = 0; i < 30; i++) {
if (config.srcDir === srcPath) {
break;
}
const b = basename(emitDtsPath);
parts.push(b);
emitDtsPath = join(emitDtsPath, '..');
srcPath = normalizePath(join(srcPath, '..'));
}
return join.apply(null, parts.reverse());
};