@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.
Files changed (48) hide show
  1. package/dist/build-cluster.js +16 -3
  2. package/dist/build-cluster.js.map +1 -1
  3. package/dist/build-tools/SdNgBundler.d.ts +1 -1
  4. package/dist/build-tools/SdNgBundler.js +4 -1
  5. package/dist/build-tools/SdNgBundler.js.map +1 -1
  6. package/dist/build-tools/SdServerBundler.js.map +1 -1
  7. package/dist/build-tools/SdTsCompiler.d.ts +5 -21
  8. package/dist/build-tools/SdTsCompiler.js +211 -188
  9. package/dist/build-tools/SdTsCompiler.js.map +1 -1
  10. package/dist/build-tools2/SdTsCompiler2.d.ts +26 -0
  11. package/dist/build-tools2/SdTsCompiler2.js +280 -0
  12. package/dist/build-tools2/SdTsCompiler2.js.map +1 -0
  13. package/dist/builders/SdCliTsLibBuilder.js +6 -11
  14. package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
  15. package/dist/bundle-plugins/sdNgPlugin.d.ts +3 -3
  16. package/dist/bundle-plugins/sdNgPlugin.js +22 -212
  17. package/dist/bundle-plugins/sdNgPlugin.js.map +1 -1
  18. package/dist/bundle-plugins/sdServerPlugin.d.ts +2 -2
  19. package/dist/bundle-plugins/sdServerPlugin.js +17 -110
  20. package/dist/bundle-plugins/sdServerPlugin.js.map +1 -1
  21. package/dist/commons.d.ts +1 -0
  22. package/dist/entry/SdCliProject.d.ts +1 -0
  23. package/dist/entry/SdCliProject.js +11 -29
  24. package/dist/entry/SdCliProject.js.map +1 -1
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/sd-cli.js +7 -1
  29. package/dist/sd-cli.js.map +1 -1
  30. package/dist/server-worker.js.map +1 -1
  31. package/dist/utils/SdCliBuildResultUtil.d.ts +10 -0
  32. package/dist/utils/SdCliBuildResultUtil.js +17 -1
  33. package/dist/utils/SdCliBuildResultUtil.js.map +1 -1
  34. package/package.json +15 -15
  35. package/src/build-cluster.ts +18 -4
  36. package/src/build-tools/SdNgBundler.ts +7 -4
  37. package/src/build-tools/SdServerBundler.ts +2 -2
  38. package/src/build-tools/SdTsCompiler.ts +64 -94
  39. package/src/build-tools2/SdTsCompiler2.ts +427 -0
  40. package/src/builders/SdCliTsLibBuilder.ts +6 -11
  41. package/src/bundle-plugins/sdNgPlugin.ts +26 -320
  42. package/src/bundle-plugins/sdServerPlugin.ts +20 -168
  43. package/src/commons.ts +1 -0
  44. package/src/entry/SdCliProject.ts +12 -30
  45. package/src/index.ts +1 -0
  46. package/src/sd-cli.ts +7 -1
  47. package/src/server-worker.ts +3 -3
  48. 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: INgResultCache;
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
- //-- stylesheetBundler
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
- //-- compilerHost
175
- const compilerHost = createCompilerHost();
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
- //-- modified
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 = new Set<string>();
209
- conf.result.affectedFileSet = new Set<string>();
210
- additionalResultMap.clear();
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
- ...diagnostics.filter(item => item.category === ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
326
- ...Array.from(additionalResultMap.values()).flatMap(item => item.errors)
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
- ...diagnostics.filter(item => item.category !== ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
330
- ...Array.from(additionalResultMap.values()).flatMap(item => item.warnings)
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
- conf.result.watchFileSet!.add(path.normalize(args.path));
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 = tscPrepareMap.get(path.normalize(args.path));
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
- outputCacheMap.set(path.normalize(args.path), newContents);
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 = outputCacheMap.get(path.normalize(args.path));
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
- outputCacheMap.set(path.normalize(args.path), newContents);
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 additionalResultMap.values()) {
404
- result.outputFiles?.push(...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 IAdditionalResult {
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: IServerBundlerResultCache;
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
- //-- compilerHost
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
- diagnostics.push(
136
- ...builder.getConfigFileParsingDiagnostics(),
137
- ...builder.getOptionsDiagnostics(),
138
- ...builder.getGlobalDiagnostics()
139
- );
18
+ let buildResult: ISdTsCompiler2Result;
140
19
 
141
- for (const affectedFile of resultCache.affectedFileSet) {
142
- const affectedSourceFile = sourceFileCache.get(path.normalize(affectedFile));
143
- if (!affectedSourceFile) {
144
- continue;
145
- }
20
+ build.onStart(async () => {
21
+ compiler.invalidate(conf.modifiedFileSet);
22
+ buildResult = await compiler.buildAsync();
146
23
 
147
- diagnostics.push(
148
- ...builder.getSyntacticDiagnostics(affectedSourceFile),
149
- ...builder.getSemanticDiagnostics(affectedSourceFile)
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: diagnostics.filter(item => item.category === ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
176
- warnings: diagnostics.filter(item => item.category !== ts.DiagnosticCategory.Error).map(item => convertTypeScriptDiagnostic(ts, item)),
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
- resultCache.watchFileSet.add(path.normalize(args.path));
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
- resultCache.watchFileSet!.add(path.normalize(args.path));
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 IServerBundlerResultCache {
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
  }
package/src/commons.ts CHANGED
@@ -28,6 +28,7 @@ export interface ISdCliBuildClusterReqMessage {
28
28
  projConf: ISdCliConfig;
29
29
  pkgPath: string;
30
30
  // builderKey?: "web" | "electron";
31
+ execArgs?: string[];
31
32
  }
32
33
 
33
34
  export interface ISdCliBuildClusterResMessage {