@simplysm/sd-cli 11.1.45 → 11.1.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-cluster.js +16 -3
- package/dist/build-cluster.js.map +1 -1
- package/dist/build-tools/SdNgBundler.d.ts +1 -1
- package/dist/build-tools/SdNgBundler.js +4 -1
- package/dist/build-tools/SdNgBundler.js.map +1 -1
- package/dist/build-tools/SdServerBundler.js.map +1 -1
- package/dist/build-tools/SdTsCompiler.d.ts +5 -21
- package/dist/build-tools/SdTsCompiler.js +211 -188
- package/dist/build-tools/SdTsCompiler.js.map +1 -1
- package/dist/build-tools2/SdTsCompiler2.d.ts +26 -0
- package/dist/build-tools2/SdTsCompiler2.js +280 -0
- package/dist/build-tools2/SdTsCompiler2.js.map +1 -0
- package/dist/builders/SdCliTsLibBuilder.js +6 -11
- package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
- package/dist/bundle-plugins/sdNgPlugin.d.ts +3 -3
- package/dist/bundle-plugins/sdNgPlugin.js +22 -212
- package/dist/bundle-plugins/sdNgPlugin.js.map +1 -1
- package/dist/bundle-plugins/sdServerPlugin.d.ts +2 -2
- package/dist/bundle-plugins/sdServerPlugin.js +17 -110
- package/dist/bundle-plugins/sdServerPlugin.js.map +1 -1
- package/dist/commons.d.ts +1 -0
- package/dist/entry/SdCliProject.d.ts +1 -0
- package/dist/entry/SdCliProject.js +11 -29
- package/dist/entry/SdCliProject.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/sd-cli.js +7 -1
- package/dist/sd-cli.js.map +1 -1
- package/dist/server-worker.js.map +1 -1
- package/dist/utils/SdCliBuildResultUtil.d.ts +10 -0
- package/dist/utils/SdCliBuildResultUtil.js +17 -1
- package/dist/utils/SdCliBuildResultUtil.js.map +1 -1
- package/package.json +15 -15
- package/src/build-cluster.ts +18 -4
- package/src/build-tools/SdNgBundler.ts +7 -4
- package/src/build-tools/SdServerBundler.ts +2 -2
- package/src/build-tools/SdTsCompiler.ts +64 -94
- package/src/build-tools2/SdTsCompiler2.ts +427 -0
- package/src/builders/SdCliTsLibBuilder.ts +6 -11
- package/src/bundle-plugins/sdNgPlugin.ts +26 -320
- package/src/bundle-plugins/sdServerPlugin.ts +20 -168
- package/src/commons.ts +1 -0
- package/src/entry/SdCliProject.ts +12 -30
- package/src/index.ts +1 -0
- package/src/sd-cli.ts +7 -1
- package/src/server-worker.ts +3 -3
- package/src/utils/SdCliBuildResultUtil.ts +22 -3
|
@@ -1,178 +1,24 @@
|
|
|
1
1
|
import esbuild from "esbuild";
|
|
2
|
-
import {FsUtil} from "@simplysm/sd-core-node";
|
|
3
2
|
import ts from "typescript";
|
|
4
3
|
import path from "path";
|
|
5
|
-
import {convertTypeScriptDiagnostic} from "@angular-devkit/build-angular/src/tools/esbuild/angular/diagnostics";
|
|
6
|
-
import {AngularCompilerHost} from "@angular-devkit/build-angular/src/tools/esbuild/angular/angular-host";
|
|
7
|
-
import {
|
|
8
|
-
ComponentStylesheetBundler
|
|
9
|
-
} from "@angular-devkit/build-angular/src/tools/esbuild/angular/component-stylesheets";
|
|
10
|
-
import {transformSupportedBrowsersToTargets} from "@angular-devkit/build-angular/src/tools/esbuild/utils";
|
|
11
|
-
import browserslist from "browserslist";
|
|
12
|
-
import {StringUtil} from "@simplysm/sd-core-common";
|
|
13
|
-
import {NgtscProgram, OptimizeFor} from "@angular/compiler-cli";
|
|
14
|
-
import {createHash} from "crypto";
|
|
15
4
|
import {JavaScriptTransformer} from "@angular-devkit/build-angular/src/tools/esbuild/javascript-transformer";
|
|
16
5
|
import os from "os";
|
|
6
|
+
import {ISdTsCompiler2Result, SdTsCompiler2} from "../build-tools2/SdTsCompiler2";
|
|
7
|
+
import {convertTypeScriptDiagnostic} from "@angular-devkit/build-angular/src/tools/esbuild/angular/diagnostics";
|
|
17
8
|
|
|
18
9
|
export function sdNgPlugin(conf: {
|
|
19
10
|
pkgPath: string;
|
|
20
11
|
dev: boolean;
|
|
21
12
|
modifiedFileSet: Set<string>;
|
|
22
|
-
result:
|
|
13
|
+
result: INgPluginResultCache;
|
|
23
14
|
}): esbuild.Plugin {
|
|
24
|
-
const tsConfigPath = path.resolve(conf.pkgPath, "tsconfig.json");
|
|
25
|
-
const tsConfig = FsUtil.readJson(tsConfigPath);
|
|
26
|
-
const parsedTsConfig = ts.parseJsonConfigFileContent(tsConfig, ts.sys, conf.pkgPath, {
|
|
27
|
-
...tsConfig.angularCompilerOptions,
|
|
28
|
-
declaration: false
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const sourceFileCache = new Map<string, ts.SourceFile>();
|
|
32
|
-
const referencingMap = new Map<string, Set<string>>();
|
|
33
|
-
|
|
34
|
-
let ngProgram: NgtscProgram | undefined;
|
|
35
|
-
let builder: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined;
|
|
36
|
-
|
|
37
|
-
// const watchFileSet = new Set<string>();
|
|
38
|
-
// const affectedFileSet = new Set<string>();
|
|
39
|
-
const additionalResultMap = new Map<string, IAdditionalResult>();
|
|
40
|
-
|
|
41
|
-
const tscPrepareMap = new Map<string, string>();
|
|
42
|
-
const outputCacheMap = new Map<string, Uint8Array>();
|
|
43
|
-
|
|
44
|
-
let stylesheetBundler: ComponentStylesheetBundler | undefined;
|
|
45
|
-
|
|
46
|
-
function createCompilerHost() {
|
|
47
|
-
const compilerHost: AngularCompilerHost = ts.createIncrementalCompilerHost(parsedTsConfig.options);
|
|
48
|
-
compilerHost.readResource = (fileName: string) => {
|
|
49
|
-
return compilerHost.readFile(fileName) ?? "";
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
compilerHost.transformResource = async (data: string, context: {
|
|
53
|
-
type: string,
|
|
54
|
-
containingFile: string,
|
|
55
|
-
resourceFile: any
|
|
56
|
-
}) => {
|
|
57
|
-
if (context.type !== "style") {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const stylesheetResult = context.resourceFile != null
|
|
62
|
-
? await stylesheetBundler!.bundleFile(context.resourceFile)
|
|
63
|
-
: await stylesheetBundler!.bundleInline(
|
|
64
|
-
data,
|
|
65
|
-
context.containingFile,
|
|
66
|
-
"scss",
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
conf.result.watchFileSet!.add(path.normalize(context.containingFile));
|
|
70
|
-
|
|
71
|
-
if (stylesheetResult.referencedFiles) {
|
|
72
|
-
for (const referencedFile of stylesheetResult.referencedFiles) {
|
|
73
|
-
const referencingMapValSet = referencingMap.getOrCreate(path.normalize(referencedFile), new Set<string>());
|
|
74
|
-
referencingMapValSet.add(path.normalize(context.containingFile));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
conf.result.watchFileSet!.adds(...Array.from(stylesheetResult.referencedFiles.values()).map(item => path.normalize(item)));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
additionalResultMap.set(path.normalize(context.resourceFile ?? context.containingFile), {
|
|
81
|
-
outputFiles: stylesheetResult.outputFiles ?? [],
|
|
82
|
-
metafile: stylesheetResult.metafile,
|
|
83
|
-
errors: stylesheetResult.errors,
|
|
84
|
-
// warnings: stylesheetResult.warnings
|
|
85
|
-
warnings: []
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return StringUtil.isNullOrEmpty(stylesheetResult.contents) ? null : {content: stylesheetResult.contents};
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
compilerHost.getModifiedResourceFiles = () => {
|
|
92
|
-
return conf.modifiedFileSet;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const baseGetSourceFile = compilerHost.getSourceFile;
|
|
96
|
-
compilerHost.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile, ...args) => {
|
|
97
|
-
if (!shouldCreateNewSourceFile && sourceFileCache.has(path.normalize(fileName))) {
|
|
98
|
-
return sourceFileCache.get(path.normalize(fileName));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const file = baseGetSourceFile.call(
|
|
102
|
-
compilerHost,
|
|
103
|
-
fileName,
|
|
104
|
-
languageVersionOrOptions,
|
|
105
|
-
onError,
|
|
106
|
-
true,
|
|
107
|
-
...args,
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
if (file) {
|
|
111
|
-
sourceFileCache.set(path.normalize(fileName), file);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return file;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
return compilerHost;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function findAffectedFileSet() {
|
|
121
|
-
const affectedFileSet = new Set<string>();
|
|
122
|
-
|
|
123
|
-
while (true) {
|
|
124
|
-
const result = builder!.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
|
125
|
-
if (ngProgram?.compiler.ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith('.ngtypecheck.ts')) {
|
|
126
|
-
const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
|
|
127
|
-
const originalSourceFile = sourceFileCache.get(originalFilename);
|
|
128
|
-
if (originalSourceFile) {
|
|
129
|
-
affectedFileSet.add(path.normalize(originalSourceFile.fileName));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return false;
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
if (!result) {
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
affectedFileSet.add(path.normalize((result.affected as ts.SourceFile).fileName));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return affectedFileSet;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
15
|
return {
|
|
149
16
|
name: "sd-ng-compiler",
|
|
150
17
|
setup: (build: esbuild.PluginBuild) => {
|
|
151
|
-
|
|
152
|
-
const browserTarget = transformSupportedBrowsersToTargets(browserslist("defaults and fully supports es6-module"));
|
|
153
|
-
stylesheetBundler = new ComponentStylesheetBundler(
|
|
154
|
-
{
|
|
155
|
-
workspaceRoot: conf.pkgPath,
|
|
156
|
-
optimization: !conf.dev,
|
|
157
|
-
inlineFonts: true,
|
|
158
|
-
preserveSymlinks: false,
|
|
159
|
-
sourcemap: 'inline', //conf.dev ? 'inline' : false,
|
|
160
|
-
outputNames: {bundles: '[name]', media: 'media/[name]'},
|
|
161
|
-
includePaths: [],
|
|
162
|
-
externalDependencies: [],
|
|
163
|
-
target: browserTarget,
|
|
164
|
-
tailwindConfiguration: undefined,
|
|
165
|
-
cacheOptions: {
|
|
166
|
-
enabled: true,
|
|
167
|
-
path: ".cache/angular",
|
|
168
|
-
basePath: ".cache"
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
conf.dev
|
|
172
|
-
);
|
|
18
|
+
const compiler = new SdTsCompiler2(conf.pkgPath, {declaration: false}, conf.dev);
|
|
173
19
|
|
|
174
|
-
|
|
175
|
-
const
|
|
20
|
+
let buildResult: ISdTsCompiler2Result;
|
|
21
|
+
const outputContentsCacheMap = new Map<string, Uint8Array>();
|
|
176
22
|
|
|
177
23
|
//-- js babel transformer
|
|
178
24
|
const javascriptTransformer = new JavaScriptTransformer({
|
|
@@ -182,165 +28,36 @@ export function sdNgPlugin(conf: {
|
|
|
182
28
|
advancedOptimizations: true
|
|
183
29
|
}, os.cpus().length);
|
|
184
30
|
|
|
185
|
-
//-- vars
|
|
186
|
-
|
|
187
31
|
//---------------------------
|
|
188
32
|
|
|
189
33
|
build.onStart(async () => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
stylesheetBundler!.invalidate(conf.modifiedFileSet);
|
|
193
|
-
for (const modifiedFile of conf.modifiedFileSet) {
|
|
194
|
-
sourceFileCache.delete(modifiedFile);
|
|
195
|
-
outputCacheMap.delete(modifiedFile);
|
|
196
|
-
|
|
197
|
-
if (referencingMap.has(modifiedFile)) {
|
|
198
|
-
for (const referencingFile of referencingMap.get(modifiedFile)!) {
|
|
199
|
-
sourceFileCache.delete(referencingFile);
|
|
200
|
-
outputCacheMap.delete(modifiedFile);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
referencingMap.clear();
|
|
205
|
-
|
|
206
|
-
//-- init resultCache
|
|
34
|
+
compiler.invalidate(conf.modifiedFileSet);
|
|
35
|
+
buildResult = await compiler.buildAsync();
|
|
207
36
|
|
|
208
|
-
conf.result.watchFileSet =
|
|
209
|
-
conf.result.affectedFileSet =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
//-- createBuilder
|
|
213
|
-
|
|
214
|
-
ngProgram = new NgtscProgram(
|
|
215
|
-
parsedTsConfig.fileNames,
|
|
216
|
-
parsedTsConfig.options,
|
|
217
|
-
compilerHost,
|
|
218
|
-
ngProgram
|
|
219
|
-
);
|
|
220
|
-
const ngCompiler = ngProgram.compiler;
|
|
221
|
-
const program = ngProgram.getTsProgram();
|
|
222
|
-
conf.result.program = program;
|
|
223
|
-
|
|
224
|
-
const baseGetSourceFiles = program.getSourceFiles;
|
|
225
|
-
program.getSourceFiles = function (...parameters) {
|
|
226
|
-
const files: readonly (ts.SourceFile & { version?: string })[] = baseGetSourceFiles(...parameters);
|
|
227
|
-
|
|
228
|
-
for (const file of files) {
|
|
229
|
-
if (file.version === undefined) {
|
|
230
|
-
file.version = createHash("sha256").update(file.text).digest("hex");
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return files;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
|
|
238
|
-
program,
|
|
239
|
-
compilerHost,
|
|
240
|
-
builder
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
await ngCompiler.analyzeAsync();
|
|
244
|
-
|
|
245
|
-
//-- affectedFilePathSet
|
|
246
|
-
|
|
247
|
-
conf.result.affectedFileSet.adds(...findAffectedFileSet());
|
|
248
|
-
|
|
249
|
-
// Deps -> refMap
|
|
250
|
-
builder.getSourceFiles().filter(sf => !ngCompiler.ignoreForEmit.has(sf))
|
|
251
|
-
.forEach(sf => {
|
|
252
|
-
conf.result.watchFileSet!.add(path.normalize(sf.fileName));
|
|
253
|
-
|
|
254
|
-
const deps = ngCompiler.getResourceDependencies(sf);
|
|
255
|
-
for (const dep of deps) {
|
|
256
|
-
const ref = referencingMap.getOrCreate(dep, new Set<string>());
|
|
257
|
-
ref.add(dep);
|
|
258
|
-
|
|
259
|
-
conf.result.watchFileSet!.add(path.normalize(dep));
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// refMap, modFile -> affectedFileSet
|
|
264
|
-
for (const modifiedFile of conf.modifiedFileSet) {
|
|
265
|
-
conf.result.affectedFileSet.adds(...referencingMap.get(modifiedFile) ?? []);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
//-- diagnostics / build
|
|
269
|
-
const diagnostics: ts.Diagnostic[] = [];
|
|
270
|
-
|
|
271
|
-
diagnostics.push(
|
|
272
|
-
...builder.getConfigFileParsingDiagnostics(),
|
|
273
|
-
...ngCompiler.getOptionDiagnostics(),
|
|
274
|
-
...builder.getOptionsDiagnostics(),
|
|
275
|
-
...builder.getGlobalDiagnostics()
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
for (const affectedFile of conf.result.affectedFileSet) {
|
|
279
|
-
const affectedSourceFile = sourceFileCache.get(path.normalize(affectedFile));
|
|
280
|
-
if (!affectedSourceFile || ngCompiler.ignoreForDiagnostics.has(affectedSourceFile)) {
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
diagnostics.push(
|
|
285
|
-
...builder.getSyntacticDiagnostics(affectedSourceFile),
|
|
286
|
-
...builder.getSemanticDiagnostics(affectedSourceFile)
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
if (affectedSourceFile.isDeclarationFile) {
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
diagnostics.push(
|
|
294
|
-
...ngCompiler.getDiagnosticsForFile(affectedSourceFile, OptimizeFor.WholeProgram),
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
//-- prepare emit cache
|
|
299
|
-
while (true) {
|
|
300
|
-
const affectedFileResult = builder.emitNextAffectedFile((fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
|
|
301
|
-
if (!sourceFiles || sourceFiles.length === 0) {
|
|
302
|
-
compilerHost.writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const sourceFile = ts.getOriginalNode(sourceFiles[0], ts.isSourceFile);
|
|
307
|
-
if (ngCompiler.ignoreForEmit.has(sourceFile)) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
ngCompiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
312
|
-
tscPrepareMap.set(path.normalize(sourceFile.fileName), text);
|
|
313
|
-
}, undefined, undefined, ngProgram.compiler.prepareEmit().transformers);
|
|
314
|
-
|
|
315
|
-
if (!affectedFileResult) {
|
|
316
|
-
break;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
diagnostics.push(...affectedFileResult.result.diagnostics);
|
|
320
|
-
}
|
|
37
|
+
conf.result.watchFileSet = buildResult.watchFileSet;
|
|
38
|
+
conf.result.affectedFileSet = buildResult.affectedFileSet;
|
|
39
|
+
conf.result.program = buildResult.program;
|
|
321
40
|
|
|
322
41
|
//-- return err/warn
|
|
323
42
|
return {
|
|
324
43
|
errors: [
|
|
325
|
-
...
|
|
326
|
-
...Array.from(
|
|
44
|
+
...buildResult.typescriptDiagnostics.filter(item => item.category === ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
|
|
45
|
+
...Array.from(buildResult.stylesheetResultMap.values()).flatMap(item => item.errors)
|
|
327
46
|
].filterExists(),
|
|
328
47
|
warnings: [
|
|
329
|
-
...
|
|
330
|
-
...Array.from(
|
|
48
|
+
...buildResult.typescriptDiagnostics.filter(item => item.category !== ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
|
|
49
|
+
// ...Array.from(buildResult.stylesheetResultMap.values()).flatMap(item => item.warnings)
|
|
331
50
|
],
|
|
332
51
|
};
|
|
333
52
|
});
|
|
334
53
|
|
|
335
54
|
build.onLoad({filter: /\.ts$/}, async (args) => {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const output = outputCacheMap.get(path.normalize(args.path));
|
|
55
|
+
const output = outputContentsCacheMap.get(path.normalize(args.path));
|
|
339
56
|
if (output != null) {
|
|
340
57
|
return {contents: output, loader: "js"};
|
|
341
58
|
}
|
|
342
59
|
|
|
343
|
-
const contents =
|
|
60
|
+
const contents = buildResult.emittedFilesCacheMap.get(path.normalize(args.path))!.last()!.text;
|
|
344
61
|
|
|
345
62
|
const {sideEffects} = await build.resolve(args.path, {
|
|
346
63
|
kind: 'import-statement',
|
|
@@ -349,12 +66,12 @@ export function sdNgPlugin(conf: {
|
|
|
349
66
|
|
|
350
67
|
const newContents = await javascriptTransformer.transformData(
|
|
351
68
|
args.path,
|
|
352
|
-
contents
|
|
69
|
+
contents,
|
|
353
70
|
true,
|
|
354
71
|
sideEffects
|
|
355
72
|
);
|
|
356
73
|
|
|
357
|
-
|
|
74
|
+
outputContentsCacheMap.set(path.normalize(args.path), newContents);
|
|
358
75
|
|
|
359
76
|
return {contents: newContents, loader: "js"};
|
|
360
77
|
});
|
|
@@ -364,7 +81,7 @@ export function sdNgPlugin(conf: {
|
|
|
364
81
|
async (args) => {
|
|
365
82
|
conf.result.watchFileSet!.add(path.normalize(args.path));
|
|
366
83
|
|
|
367
|
-
const output =
|
|
84
|
+
const output = outputContentsCacheMap.get(path.normalize(args.path));
|
|
368
85
|
if (output != null) {
|
|
369
86
|
return {contents: output, loader: "js"};
|
|
370
87
|
}
|
|
@@ -374,15 +91,13 @@ export function sdNgPlugin(conf: {
|
|
|
374
91
|
resolveDir: build.initialOptions.absWorkingDir ?? '',
|
|
375
92
|
});
|
|
376
93
|
|
|
377
|
-
// const contents = await FsUtil.readFileAsync(args.path);
|
|
378
|
-
|
|
379
94
|
const newContents = await javascriptTransformer.transformFile(
|
|
380
95
|
args.path,
|
|
381
96
|
false,
|
|
382
97
|
sideEffects
|
|
383
98
|
);
|
|
384
99
|
|
|
385
|
-
|
|
100
|
+
outputContentsCacheMap.set(path.normalize(args.path), newContents);
|
|
386
101
|
|
|
387
102
|
return {
|
|
388
103
|
contents: newContents,
|
|
@@ -400,8 +115,9 @@ export function sdNgPlugin(conf: {
|
|
|
400
115
|
);
|
|
401
116
|
|
|
402
117
|
build.onEnd((result) => {
|
|
403
|
-
for (const {outputFiles, metafile} of
|
|
404
|
-
result.outputFiles
|
|
118
|
+
for (const {outputFiles, metafile} of buildResult.stylesheetResultMap.values()) {
|
|
119
|
+
result.outputFiles = result.outputFiles ?? [];
|
|
120
|
+
result.outputFiles.push(...outputFiles);
|
|
405
121
|
|
|
406
122
|
if (result.metafile && metafile) {
|
|
407
123
|
result.metafile.inputs = {...result.metafile.inputs, ...metafile.inputs};
|
|
@@ -409,9 +125,6 @@ export function sdNgPlugin(conf: {
|
|
|
409
125
|
}
|
|
410
126
|
}
|
|
411
127
|
|
|
412
|
-
// conf.result.watchFileSet = resultCache.watchFileSet;
|
|
413
|
-
// conf.result.affectedFileSet = resultCache.affectedFileSet;
|
|
414
|
-
// conf.result.program = ngProgram!.getTsProgram();
|
|
415
128
|
conf.result.outputFiles = result.outputFiles;
|
|
416
129
|
conf.result.metafile = result.metafile;
|
|
417
130
|
|
|
@@ -421,17 +134,10 @@ export function sdNgPlugin(conf: {
|
|
|
421
134
|
};
|
|
422
135
|
}
|
|
423
136
|
|
|
424
|
-
interface
|
|
425
|
-
outputFiles: esbuild.OutputFile[];
|
|
426
|
-
metafile?: esbuild.Metafile;
|
|
427
|
-
errors?: esbuild.PartialMessage[];
|
|
428
|
-
warnings: esbuild.PartialMessage[];
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
export interface INgResultCache {
|
|
137
|
+
export interface INgPluginResultCache {
|
|
432
138
|
watchFileSet?: Set<string>;
|
|
433
139
|
affectedFileSet?: Set<string>;
|
|
140
|
+
program?: ts.Program;
|
|
434
141
|
outputFiles?: esbuild.OutputFile[];
|
|
435
142
|
metafile?: esbuild.Metafile;
|
|
436
|
-
program?: ts.Program;
|
|
437
143
|
}
|
|
@@ -1,203 +1,60 @@
|
|
|
1
1
|
import esbuild from "esbuild";
|
|
2
|
-
import {FsUtil} from "@simplysm/sd-core-node";
|
|
3
2
|
import ts from "typescript";
|
|
4
3
|
import path from "path";
|
|
5
4
|
import {convertTypeScriptDiagnostic} from "@angular-devkit/build-angular/src/tools/esbuild/angular/diagnostics";
|
|
5
|
+
import {ISdTsCompiler2Result, SdTsCompiler2} from "../build-tools2/SdTsCompiler2";
|
|
6
6
|
|
|
7
7
|
export function sdServerPlugin(conf: {
|
|
8
8
|
pkgPath: string;
|
|
9
9
|
dev: boolean;
|
|
10
10
|
modifiedFileSet: Set<string>;
|
|
11
|
-
result:
|
|
11
|
+
result: IServerPluginResultCache;
|
|
12
12
|
}): esbuild.Plugin {
|
|
13
|
-
const tsConfigPath = path.resolve(conf.pkgPath, "tsconfig.json");
|
|
14
|
-
const tsConfig = FsUtil.readJson(tsConfigPath);
|
|
15
|
-
const parsedTsConfig = ts.parseJsonConfigFileContent(tsConfig, ts.sys, conf.pkgPath, {
|
|
16
|
-
declaration: false
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const sourceFileCache = new Map<string, ts.SourceFile>();
|
|
20
|
-
const referencingMap = new Map<string, Set<string>>();
|
|
21
|
-
|
|
22
|
-
let program: ts.Program | undefined;
|
|
23
|
-
let builder: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined;
|
|
24
|
-
|
|
25
|
-
let resultCache: IResultCache = {
|
|
26
|
-
watchFileSet: new Set<string>(),
|
|
27
|
-
affectedFileSet: new Set<string>()
|
|
28
|
-
};
|
|
29
|
-
const tscPrepareMap = new Map<string, string>();
|
|
30
|
-
|
|
31
|
-
function createCompilerHost() {
|
|
32
|
-
const compilerHost = ts.createIncrementalCompilerHost(parsedTsConfig.options);
|
|
33
|
-
const baseGetSourceFile = compilerHost.getSourceFile;
|
|
34
|
-
compilerHost.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile, ...args) => {
|
|
35
|
-
if (!shouldCreateNewSourceFile && sourceFileCache.has(path.normalize(fileName))) {
|
|
36
|
-
return sourceFileCache.get(path.normalize(fileName));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const file = baseGetSourceFile.call(
|
|
40
|
-
compilerHost,
|
|
41
|
-
fileName,
|
|
42
|
-
languageVersionOrOptions,
|
|
43
|
-
onError,
|
|
44
|
-
true,
|
|
45
|
-
...args,
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
if (file) {
|
|
49
|
-
sourceFileCache.set(path.normalize(fileName), file);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return file;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
return compilerHost;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function findAffectedFileSet() {
|
|
59
|
-
const affectedFileSet = new Set<string>();
|
|
60
|
-
|
|
61
|
-
while (true) {
|
|
62
|
-
const result = builder!.getSemanticDiagnosticsOfNextAffectedFile();
|
|
63
|
-
if (!result) {
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
affectedFileSet.add(path.normalize((result.affected as ts.SourceFile).fileName));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return affectedFileSet;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
13
|
return {
|
|
73
14
|
name: "sd-server-compiler",
|
|
74
15
|
setup: (build: esbuild.PluginBuild) => {
|
|
75
|
-
|
|
76
|
-
const compilerHost = createCompilerHost();
|
|
77
|
-
|
|
78
|
-
build.onStart(() => {
|
|
79
|
-
//-- modified
|
|
80
|
-
for (const modifiedFile of conf.modifiedFileSet) {
|
|
81
|
-
sourceFileCache.delete(modifiedFile);
|
|
82
|
-
|
|
83
|
-
if (referencingMap.has(modifiedFile)) {
|
|
84
|
-
for (const referencingFile of referencingMap.get(modifiedFile)!) {
|
|
85
|
-
sourceFileCache.delete(referencingFile);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
referencingMap.clear();
|
|
90
|
-
|
|
91
|
-
//-- init resultCache
|
|
92
|
-
|
|
93
|
-
resultCache = {
|
|
94
|
-
watchFileSet: new Set<string>(),
|
|
95
|
-
affectedFileSet: new Set<string>(),
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
program = ts.createProgram(
|
|
99
|
-
parsedTsConfig.fileNames,
|
|
100
|
-
parsedTsConfig.options,
|
|
101
|
-
compilerHost,
|
|
102
|
-
program
|
|
103
|
-
);
|
|
104
|
-
builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
|
|
105
|
-
program,
|
|
106
|
-
compilerHost,
|
|
107
|
-
builder
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
//-- affectedFilePathSet
|
|
111
|
-
resultCache.affectedFileSet.adds(...findAffectedFileSet());
|
|
112
|
-
|
|
113
|
-
// Deps -> refMap
|
|
114
|
-
builder.getSourceFiles().forEach(sf => {
|
|
115
|
-
resultCache.watchFileSet.add(path.normalize(sf.fileName));
|
|
116
|
-
|
|
117
|
-
const deps = builder!.getAllDependencies(sf);
|
|
118
|
-
for (const dep of deps) {
|
|
119
|
-
const ref = referencingMap.getOrCreate(dep, new Set<string>());
|
|
120
|
-
ref.add(dep);
|
|
121
|
-
|
|
122
|
-
resultCache.watchFileSet.add(path.normalize(dep));
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// refMap, modFile -> affectedFileSet
|
|
127
|
-
for (const modifiedFile of conf.modifiedFileSet) {
|
|
128
|
-
resultCache.affectedFileSet.adds(...referencingMap.get(modifiedFile) ?? []);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
//-- diagnostics / build
|
|
132
|
-
|
|
133
|
-
const diagnostics: ts.Diagnostic[] = [];
|
|
16
|
+
const compiler = new SdTsCompiler2(conf.pkgPath, {declaration: false}, conf.dev);
|
|
134
17
|
|
|
135
|
-
|
|
136
|
-
...builder.getConfigFileParsingDiagnostics(),
|
|
137
|
-
...builder.getOptionsDiagnostics(),
|
|
138
|
-
...builder.getGlobalDiagnostics()
|
|
139
|
-
);
|
|
18
|
+
let buildResult: ISdTsCompiler2Result;
|
|
140
19
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
20
|
+
build.onStart(async () => {
|
|
21
|
+
compiler.invalidate(conf.modifiedFileSet);
|
|
22
|
+
buildResult = await compiler.buildAsync();
|
|
146
23
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
//-- prepare emit cache
|
|
154
|
-
while (true) {
|
|
155
|
-
const affectedFileResult = builder.emitNextAffectedFile((fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
|
|
156
|
-
if (!sourceFiles || sourceFiles.length === 0) {
|
|
157
|
-
compilerHost.writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const sourceFile = ts.getOriginalNode(sourceFiles[0], ts.isSourceFile);
|
|
162
|
-
tscPrepareMap.set(path.normalize(sourceFile.fileName), text);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
if (!affectedFileResult) {
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
diagnostics.push(...affectedFileResult.result.diagnostics);
|
|
170
|
-
}
|
|
24
|
+
conf.result.watchFileSet = buildResult.watchFileSet;
|
|
25
|
+
conf.result.affectedFileSet = buildResult.affectedFileSet;
|
|
26
|
+
conf.result.program = buildResult.program;
|
|
171
27
|
|
|
172
28
|
//-- return err/warn
|
|
173
29
|
|
|
174
30
|
return {
|
|
175
|
-
errors:
|
|
176
|
-
warnings:
|
|
31
|
+
errors: buildResult.typescriptDiagnostics.filter(item => item.category === ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
|
|
32
|
+
warnings: buildResult.typescriptDiagnostics.filter(item => item.category !== ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
|
|
177
33
|
};
|
|
178
34
|
});
|
|
179
35
|
|
|
180
36
|
|
|
181
37
|
build.onLoad({filter: /\.ts$/}, (args) => {
|
|
182
|
-
|
|
183
|
-
const contents = tscPrepareMap.get(path.normalize(args.path));
|
|
38
|
+
const contents = buildResult.emittedFilesCacheMap.get(path.normalize(args.path))!.last()!.text;
|
|
184
39
|
return {contents, loader: "js"};
|
|
185
40
|
});
|
|
186
41
|
|
|
42
|
+
build.onLoad({filter: /\.[cm]?js$/}, (args) => {
|
|
43
|
+
conf.result.watchFileSet!.add(path.normalize(args.path));
|
|
44
|
+
return null;
|
|
45
|
+
});
|
|
46
|
+
|
|
187
47
|
build.onLoad(
|
|
188
48
|
{filter: new RegExp("(" + Object.keys(build.initialOptions.loader!).map(item => "\\" + item).join("|") + ")$")},
|
|
189
49
|
(args) => {
|
|
190
|
-
|
|
50
|
+
conf.result.watchFileSet!.add(path.normalize(args.path));
|
|
191
51
|
return null;
|
|
192
52
|
}
|
|
193
53
|
);
|
|
194
54
|
|
|
195
55
|
build.onEnd((result) => {
|
|
196
|
-
conf.result.watchFileSet = resultCache.watchFileSet;
|
|
197
|
-
conf.result.affectedFileSet = resultCache.affectedFileSet;
|
|
198
56
|
conf.result.outputFiles = result.outputFiles;
|
|
199
57
|
conf.result.metafile = result.metafile;
|
|
200
|
-
conf.result.program = program;
|
|
201
58
|
|
|
202
59
|
conf.modifiedFileSet.clear();
|
|
203
60
|
});
|
|
@@ -205,15 +62,10 @@ export function sdServerPlugin(conf: {
|
|
|
205
62
|
};
|
|
206
63
|
}
|
|
207
64
|
|
|
208
|
-
export interface
|
|
65
|
+
export interface IServerPluginResultCache {
|
|
209
66
|
watchFileSet?: Set<string>;
|
|
210
67
|
affectedFileSet?: Set<string>;
|
|
211
68
|
outputFiles?: esbuild.OutputFile[];
|
|
212
69
|
metafile?: esbuild.Metafile;
|
|
213
70
|
program?: ts.Program;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
interface IResultCache {
|
|
217
|
-
watchFileSet: Set<string>;
|
|
218
|
-
affectedFileSet: Set<string>;
|
|
219
71
|
}
|