@simplysm/sd-cli 6.0.19 → 6.0.27

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 (99) hide show
  1. package/.eslintrc.js +1 -2
  2. package/dist-node/bin/sd-cli.js +25 -8
  3. package/dist-node/bin/sd-cli.js.map +1 -1
  4. package/dist-node/build-tools/SdCliIndexFileGenerator.js +51 -0
  5. package/dist-node/build-tools/SdCliIndexFileGenerator.js.map +1 -0
  6. package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js +621 -0
  7. package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js.map +1 -0
  8. package/dist-node/build-tools/metadata/SdAotMetadataReader.js +270 -0
  9. package/dist-node/build-tools/metadata/SdAotMetadataReader.js.map +1 -0
  10. package/dist-node/build-tools/metadata/SdIvyMetadataReader.js +101 -0
  11. package/dist-node/build-tools/metadata/SdIvyMetadataReader.js.map +1 -0
  12. package/dist-node/build-tools/metadata/SdMyMetadataReader.js +298 -0
  13. package/dist-node/build-tools/metadata/SdMyMetadataReader.js.map +1 -0
  14. package/dist-node/{build-tools → builders}/SdCliJavascriptLinter.js +1 -1
  15. package/dist-node/builders/SdCliJavascriptLinter.js.map +1 -0
  16. package/dist-node/{build-tools → builders}/SdCliNgClientBuilder.js +176 -102
  17. package/dist-node/builders/SdCliNgClientBuilder.js.map +1 -0
  18. package/dist-node/builders/SdCliNgLibraryBuilder.js +238 -0
  19. package/dist-node/builders/SdCliNgLibraryBuilder.js.map +1 -0
  20. package/dist-node/{build-tools → builders}/SdCliPublisher.js +0 -0
  21. package/dist-node/builders/SdCliPublisher.js.map +1 -0
  22. package/dist-node/{build-tools → builders}/SdCliServerBuilder.js +8 -6
  23. package/dist-node/builders/SdCliServerBuilder.js.map +1 -0
  24. package/dist-node/builders/SdCliTypescriptBuilder.js +304 -0
  25. package/dist-node/builders/SdCliTypescriptBuilder.js.map +1 -0
  26. package/dist-node/entry-points/SdCliLocalUpdater.js +9 -8
  27. package/dist-node/entry-points/SdCliLocalUpdater.js.map +1 -1
  28. package/dist-node/entry-points/SdCliProject.js +11 -9
  29. package/dist-node/entry-points/SdCliProject.js.map +1 -1
  30. package/dist-node/packages/SdCliClientPackage.js +12 -2
  31. package/dist-node/packages/SdCliClientPackage.js.map +1 -1
  32. package/dist-node/packages/SdCliLibraryPackage.js +17 -9
  33. package/dist-node/packages/SdCliLibraryPackage.js.map +1 -1
  34. package/dist-node/packages/SdCliServerPackage.js +2 -2
  35. package/dist-node/packages/SdCliServerPackage.js.map +1 -1
  36. package/dist-node/utils/SdCliFileCrypto.js +76 -0
  37. package/dist-node/utils/SdCliFileCrypto.js.map +1 -0
  38. package/dist-node/utils/SdProjectConfigUtil.js +1 -1
  39. package/dist-node/utils/SdProjectConfigUtil.js.map +1 -1
  40. package/dist-node/utils/SdWebpackUtil.js +12 -3
  41. package/dist-node/utils/SdWebpackUtil.js.map +1 -1
  42. package/dist-node/workers/lib-build-worker.js +7 -6
  43. package/dist-node/workers/lib-build-worker.js.map +1 -1
  44. package/dist-types/build-tools/SdCliIndexFileGenerator.d.ts +12 -0
  45. package/dist-types/build-tools/SdCliNgModuleFilesGenerator.d.ts +42 -0
  46. package/dist-types/build-tools/metadata/SdAotMetadataReader.d.ts +57 -0
  47. package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts +41 -0
  48. package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts +57 -0
  49. package/dist-types/{build-tools → builders}/SdCliJavascriptLinter.d.ts +0 -0
  50. package/dist-types/{build-tools → builders}/SdCliNgClientBuilder.d.ts +1 -1
  51. package/dist-types/builders/SdCliNgLibraryBuilder.d.ts +27 -0
  52. package/dist-types/{build-tools → builders}/SdCliPublisher.d.ts +0 -0
  53. package/dist-types/{build-tools → builders}/SdCliServerBuilder.d.ts +0 -0
  54. package/dist-types/builders/SdCliTypescriptBuilder.d.ts +46 -0
  55. package/dist-types/commons.d.ts +11 -3
  56. package/dist-types/packages/SdCliClientPackage.d.ts +1 -1
  57. package/dist-types/utils/SdCliFileCrypto.d.ts +7 -0
  58. package/dist-types/utils/SdWebpackUtil.d.ts +1 -0
  59. package/package.json +10 -7
  60. package/schema/schema.json +247 -0
  61. package/src/bin/sd-cli.ts +37 -14
  62. package/src/build-tools/SdCliIndexFileGenerator.ts +61 -0
  63. package/src/build-tools/SdCliNgModuleFilesGenerator.ts +837 -0
  64. package/src/build-tools/metadata/SdAotMetadataReader.ts +368 -0
  65. package/src/build-tools/metadata/SdIvyMetadataReader.ts +152 -0
  66. package/src/build-tools/metadata/SdMyMetadataReader.ts +379 -0
  67. package/src/{build-tools → builders}/SdCliJavascriptLinter.ts +1 -1
  68. package/src/{build-tools → builders}/SdCliNgClientBuilder.ts +209 -111
  69. package/src/builders/SdCliNgLibraryBuilder.ts +336 -0
  70. package/src/{build-tools → builders}/SdCliPublisher.ts +0 -0
  71. package/src/{build-tools → builders}/SdCliServerBuilder.ts +14 -8
  72. package/src/builders/SdCliTypescriptBuilder.ts +488 -0
  73. package/src/commons.ts +11 -3
  74. package/src/entry-points/SdCliLocalUpdater.ts +9 -8
  75. package/src/entry-points/SdCliProject.ts +12 -9
  76. package/src/packages/SdCliClientPackage.ts +14 -3
  77. package/src/packages/SdCliLibraryPackage.ts +19 -11
  78. package/src/packages/SdCliServerPackage.ts +2 -2
  79. package/src/utils/SdCliFileCrypto.ts +87 -0
  80. package/src/utils/SdCliUtils.ts +56 -0
  81. package/src/utils/SdProjectConfigUtil.ts +1 -1
  82. package/src/utils/SdWebpackUtil.ts +13 -3
  83. package/src/workers/lib-build-worker.ts +8 -7
  84. package/dist-node/build-tools/SdCliJavascriptLinter.js.map +0 -1
  85. package/dist-node/build-tools/SdCliNgClientBuilder.js.map +0 -1
  86. package/dist-node/build-tools/SdCliNgLibraryBuilder.js +0 -164
  87. package/dist-node/build-tools/SdCliNgLibraryBuilder.js.map +0 -1
  88. package/dist-node/build-tools/SdCliPublisher.js.map +0 -1
  89. package/dist-node/build-tools/SdCliServerBuilder.js.map +0 -1
  90. package/dist-node/build-tools/SdCliTypescriptBuilder.js +0 -316
  91. package/dist-node/build-tools/SdCliTypescriptBuilder.js.map +0 -1
  92. package/dist-node/build-tools/SdCliTypescriptIndexFileGenerator.js +0 -75
  93. package/dist-node/build-tools/SdCliTypescriptIndexFileGenerator.js.map +0 -1
  94. package/dist-types/build-tools/SdCliNgLibraryBuilder.d.ts +0 -23
  95. package/dist-types/build-tools/SdCliTypescriptBuilder.d.ts +0 -37
  96. package/dist-types/build-tools/SdCliTypescriptIndexFileGenerator.d.ts +0 -12
  97. package/src/build-tools/SdCliNgLibraryBuilder.ts +0 -225
  98. package/src/build-tools/SdCliTypescriptBuilder.ts +0 -424
  99. package/src/build-tools/SdCliTypescriptIndexFileGenerator.ts +0 -93
@@ -1,225 +0,0 @@
1
- import * as ts from "typescript";
2
- import { ISdPackageBuildResult } from "../commons";
3
- import * as path from "path";
4
- import { SdTsDiagnosticUtil } from "../utils/SdTsDiagnosticUtil";
5
- import { NgccProcessingCache } from "ng-packagr/lib/ng-package/ngcc-cache";
6
- import { NgccProcessor } from "ng-packagr/lib/ngc/ngcc-processor";
7
- import { EntryPointNode } from "ng-packagr/lib/ng-package/nodes";
8
- import { ngccTransformCompilerHost } from "ng-packagr/lib/ts/ngcc-transform-compiler-host";
9
- import { NgtscProgram } from "@angular/compiler-cli";
10
- import { ITsBuildFileCache, SdCliTypescriptBuilder } from "./SdCliTypescriptBuilder";
11
- import { NgCompiler } from "@angular/compiler-cli/src/ngtsc/core";
12
- import { NeverEntryError } from "@simplysm/sd-core-common";
13
- import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
14
- import * as os from "os";
15
- import * as nodeSass from "node-sass";
16
- import { createHash } from "crypto";
17
-
18
- export class SdCliNgLibraryBuilder extends SdCliTypescriptBuilder {
19
- protected _ngProgram?: NgtscProgram;
20
- protected _ngCompiler?: NgCompiler;
21
- private readonly _ngccProcessingCache = new NgccProcessingCache();
22
-
23
- protected override readonly _fileCache = new Map<string, (ITsBuildFileCache & { scssResult?: { content: string; dependencies: string[] } })>();
24
-
25
- public constructor(public rootPath: string,
26
- public tsconfigFilePath: string) {
27
- super(rootPath, tsconfigFilePath);
28
-
29
- this._parsedTsconfig = {
30
- ...this._parsedTsconfig,
31
- options: {
32
- baseUrl: path.dirname(this.tsconfigFilePath),
33
- enableI18nLegacyMessageIdFormat: false,
34
- strictInjectionParameters: true,
35
- strictInputAccessModifiers: true,
36
- strictTemplates: true,
37
- strictInputTypes: false,
38
- ...this._parsedTsconfig.options
39
- }
40
- };
41
- }
42
-
43
- protected override async _runProgramAsync(dirtySourceFiles?: ts.SourceFile[]): Promise<ISdPackageBuildResult[]> {
44
- if (!this._ngCompiler) throw new NeverEntryError();
45
- if (!this._builder) throw new NeverEntryError();
46
-
47
- const diagnostics = [
48
- ...this._ngCompiler.getOptionDiagnostics(),
49
- ...this._builder.getOptionsDiagnostics(),
50
- ...this._builder.getGlobalDiagnostics()
51
- ];
52
-
53
- await this._ngCompiler.analyzeAsync();
54
-
55
- const currDirtySourceFiles = dirtySourceFiles ?? this._builder.getSourceFiles();
56
-
57
- for (const sourceFile of currDirtySourceFiles) {
58
- diagnostics.push(...[
59
- ...this._builder.getSyntacticDiagnostics(sourceFile),
60
- ...this._builder.getSemanticDiagnostics(sourceFile)
61
- ]);
62
- }
63
-
64
- const transformers = this._ngCompiler.prepareEmit().transformers;
65
-
66
- for (const sourceFile of currDirtySourceFiles) {
67
- this._builder.emit(sourceFile, undefined, undefined, undefined, transformers);
68
- }
69
-
70
- return diagnostics.map((item) => SdTsDiagnosticUtil.convertDiagnosticsToResult(item)).filterExists();
71
- }
72
-
73
- protected override _reloadProgram(watch: boolean): ts.SourceFile[] | undefined {
74
- const moduleResolutionCache = ts.createModuleResolutionCache(this.rootPath, (s) => s, this._parsedTsconfig.options);
75
- const cacheCompilerHost = this._createCacheCompilerHost(this._parsedTsconfig, moduleResolutionCache);
76
-
77
- this._ngProgram = new NgtscProgram(
78
- this._parsedTsconfig.fileNames,
79
- this._parsedTsconfig.options,
80
- cacheCompilerHost,
81
- this._ngProgram
82
- );
83
-
84
- this._ngCompiler = this._ngProgram.compiler;
85
- this._program = this._ngProgram.getTsProgram();
86
-
87
- const baseGetSourceFiles = this._program.getSourceFiles;
88
- this._program.getSourceFiles = function (...parameters) {
89
- const files: readonly (ts.SourceFile & { version?: string })[] = baseGetSourceFiles(...parameters);
90
-
91
- for (const file of files) {
92
- if (file.version === undefined) {
93
- file.version = createHash("sha256").update(file.text).digest("hex");
94
- }
95
- }
96
-
97
- return files;
98
- };
99
-
100
- if (watch) {
101
- const builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
102
- this._program,
103
- cacheCompilerHost,
104
- this._builder as ts.EmitAndSemanticDiagnosticsBuilderProgram
105
- );
106
- this._builder = builder;
107
-
108
- const results: ts.SourceFile[] = [];
109
- while (true) {
110
- const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
111
- return this._ngCompiler!.ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith(".ngtypecheck.ts");
112
- });
113
-
114
- if (result && "fileName" in result.affected) {
115
- results.push(result.affected);
116
- }
117
- if (!result) break;
118
- }
119
- return results;
120
- }
121
- else {
122
- this._builder = ts.createAbstractBuilder(this._program, cacheCompilerHost);
123
- return undefined;
124
- }
125
- }
126
-
127
- protected override _createCacheCompilerHost(parsedTsconfig: ts.ParsedCommandLine, moduleResolutionCache: ts.ModuleResolutionCache): ts.CompilerHost {
128
- const tsCacheCompilerHost = super._createCacheCompilerHost(parsedTsconfig, moduleResolutionCache);
129
-
130
- const ngccProcessor = new NgccProcessor(
131
- this._ngccProcessingCache,
132
- this.tsconfigFilePath,
133
- parsedTsconfig.options,
134
- parsedTsconfig.fileNames.map((item) => ({ url: item }) as EntryPointNode)
135
- );
136
-
137
- const ngCompilerHost = ngccTransformCompilerHost(
138
- tsCacheCompilerHost,
139
- parsedTsconfig.options,
140
- ngccProcessor,
141
- moduleResolutionCache
142
- );
143
-
144
- const resultCompilerHost = { ...ngCompilerHost };
145
- resultCompilerHost.writeFile = (fileName: string,
146
- data: string,
147
- writeByteOrderMark: boolean,
148
- onError?: (message: string) => void,
149
- sourceFiles?: readonly ts.SourceFile[]) => {
150
- if (!fileName.includes(".ngtypecheck.")) {
151
- ngCompilerHost.writeFile.call(resultCompilerHost, fileName, data, writeByteOrderMark, onError, sourceFiles);
152
- }
153
- };
154
-
155
- resultCompilerHost.getSourceFile = (fileName: string, languageVersion: ts.ScriptTarget) => {
156
- const cache = this._fileCache.getOrCreate(PathUtil.posix(fileName), {});
157
-
158
- if (cache.scssResult === undefined && fileName.endsWith(".ts") && !fileName.endsWith(".d.ts")) {
159
- const orgContent = FsUtil.readFile(fileName);
160
- cache.scssResult = this._replaceScssToCss(fileName, orgContent);
161
- }
162
- if (cache.sourceFile === undefined) {
163
- if (cache.scssResult) {
164
- cache.sourceFile = ts.createSourceFile(fileName, cache.scssResult.content, languageVersion);
165
- }
166
- else {
167
- cache.sourceFile = ngCompilerHost.getSourceFile.call(resultCompilerHost, fileName, languageVersion);
168
- }
169
- }
170
- if (cache.dependencyFilePaths === undefined) {
171
- cache.dependencyFilePaths = [
172
- ...this._getDependencyFilePaths(
173
- cache.sourceFile!,
174
- parsedTsconfig.options,
175
- ngCompilerHost,
176
- moduleResolutionCache
177
- ),
178
- ...cache.scssResult ? cache.scssResult.dependencies : []
179
- ];
180
- }
181
- return cache.sourceFile;
182
- };
183
-
184
- return resultCompilerHost;
185
- }
186
-
187
- private _replaceScssToCss(filePath: string, content: string): { content: string; dependencies: string[] } {
188
- const scssRegex = /\/\* *language=SCSS *\*\/ *[`"'](((?!['"`]\)?[\],][,;]?[\r\n\\])(.|\r|\n))*)['"`]/;
189
-
190
- const matches = content.match(new RegExp(scssRegex, "gi"));
191
- if (!matches) {
192
- return { content, dependencies: [] };
193
- }
194
-
195
- const results = matches.map((match) => nodeSass.renderSync({
196
- file: filePath,
197
- data: scssRegex.exec(match)?.[1],
198
- precision: 8,
199
- includePaths: [],
200
- outputStyle: "expanded",
201
- sourceMapEmbed: false,
202
- sourceMap: false
203
- }));
204
-
205
- const deps = results.mapMany((result) => result.stats.includedFiles).map((item) => path.resolve(item));
206
-
207
- let i = 0;
208
- const newContent = content.replace(new RegExp(scssRegex, "gi"), () => {
209
- let result = "`" + results[i].css.toString() + "`";
210
- const prev = matches[i];
211
-
212
- const diffCount = Array.from(prev).filter((item) => item === "\n").length
213
- - Array.from(result).filter((item) => item === "\n").length;
214
-
215
- for (let j = 0; j < diffCount; j++) {
216
- result += os.EOL;
217
- }
218
-
219
- i += 1;
220
- return result;
221
- });
222
-
223
- return { content: newContent, dependencies: deps };
224
- }
225
- }
@@ -1,424 +0,0 @@
1
- import * as ts from "typescript";
2
- import { INpmConfig, ISdPackageBuildResult, ITsconfig } from "../commons";
3
- import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core-node";
4
- import { NeverEntryError, StringUtil } from "@simplysm/sd-core-common";
5
- import { EventEmitter } from "events";
6
- import * as path from "path";
7
- import { SdTsDiagnosticUtil } from "../utils/SdTsDiagnosticUtil";
8
- import { ESLint } from "eslint";
9
- import { createHash } from "crypto";
10
-
11
- export class SdCliTypescriptBuilder extends EventEmitter {
12
- private readonly _logger: Logger;
13
-
14
- protected _parsedTsconfig: ts.ParsedCommandLine;
15
- public readonly npmConfig: INpmConfig;
16
-
17
- protected _program?: ts.Program;
18
- protected _builder?: ts.BuilderProgram | ts.EmitAndSemanticDiagnosticsBuilderProgram;
19
- protected readonly _fileCache: Map<string, ITsBuildFileCache> = new Map<string, ITsBuildFileCache>();
20
-
21
- private readonly _resultMap = new Map<string, ISdPackageBuildResult[]>();
22
-
23
- public constructor(public rootPath: string,
24
- public tsconfigFilePath: string,
25
- public noEmit: boolean = false) {
26
- super();
27
-
28
- const tsconfig: ITsconfig = FsUtil.readJson(this.tsconfigFilePath);
29
- this._parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this.rootPath);
30
-
31
- this.npmConfig = FsUtil.readJson(path.resolve(this.rootPath, "package.json"));
32
- this._logger = Logger.get(["simplysm", "sd-cli", this.constructor.name, this.npmConfig.name]);
33
- }
34
-
35
- public on(event: "change", listener: () => void): this;
36
- public on(event: "complete", listener: (results: ISdPackageBuildResult[]) => void): this;
37
- public on(event: string | symbol, listener: (...args: any[]) => void): this {
38
- return super.on(event, listener);
39
- }
40
-
41
- public async buildAsync(watch: boolean): Promise<void> {
42
- this.emit("change");
43
-
44
- // DIST 비우기
45
- await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
46
- if (this._parsedTsconfig.options.declarationDir !== undefined) {
47
- await FsUtil.removeAsync(this._parsedTsconfig.options.declarationDir);
48
- }
49
-
50
- this._reloadProgram(watch);
51
-
52
- if (watch) {
53
- const watchPaths = this._getWatchPaths();
54
- const watcher = new SdFsWatcher();
55
- watcher
56
- .on("change", async (changeInfos) => {
57
- try {
58
- const dirtyFilePaths = changeInfos
59
- .map((item) => PathUtil.posix(item.filePath))
60
- .filter((item) => path.basename(item).includes("."))
61
- .distinct();
62
- if (dirtyFilePaths.length === 0) return;
63
-
64
- this.emit("change");
65
-
66
- this._deleteFileCaches(dirtyFilePaths);
67
-
68
- const reloadedSourceFiles = this._reloadProgram(watch)!;
69
-
70
- const watchPaths2 = this._getWatchPaths();
71
- watcher.replaceWatchPaths(watchPaths2);
72
-
73
- // 빌드 및 린트
74
- const results = await this._doAllAsync(reloadedSourceFiles);
75
-
76
- // 결과 MAP에서 DIRTY FILE 삭제
77
- this._resultMap.delete("undefined");
78
- const allDirtyPosixFilePaths = reloadedSourceFiles
79
- .map((item) => item.fileName)
80
- .concat(dirtyFilePaths)
81
- .map((item) => PathUtil.posix(item))
82
- .distinct();
83
- for (const allDirtyPosixFilePath of allDirtyPosixFilePaths) {
84
- this._resultMap.delete(allDirtyPosixFilePath);
85
- }
86
-
87
- // 결과 MAP 구성
88
- for (const result of results) {
89
- const posixFilePath = result.filePath !== undefined ? PathUtil.posix(result.filePath) : "undefined";
90
- const resultMapValue = this._resultMap.getOrCreate(posixFilePath, []);
91
- resultMapValue.push(result);
92
- }
93
-
94
- this.emit("complete", Array.from(this._resultMap.values()).mapMany());
95
- }
96
- catch (err) {
97
- this.emit("complete", [{
98
- filePath: undefined,
99
- severity: "error",
100
- message: err.stack ?? err.message
101
- }]);
102
- }
103
- })
104
- .watch(watchPaths);
105
-
106
- // 빌드 및 린트
107
- const results = await this._doAllAsync();
108
-
109
- // 결과 MAP 구성
110
- for (const result of results) {
111
- const posixFilePath = result.filePath !== undefined ? PathUtil.posix(result.filePath) : "undefined";
112
- const resultMapValue = this._resultMap.getOrCreate(posixFilePath, []);
113
- resultMapValue.push(result);
114
- }
115
- this.emit("complete", Array.from(this._resultMap.values()).mapMany());
116
- }
117
- else {
118
- const results = await this._doAllAsync();
119
- this.emit("complete", results);
120
- }
121
- }
122
-
123
- protected async _doAllAsync(dirtySourceFiles?: ts.SourceFile[]): Promise<ISdPackageBuildResult[]> {
124
- return (
125
- await Promise.all([
126
- (async () => {
127
- this._logger.debug("빌드 시작");
128
- const result = await this._runProgramAsync(dirtySourceFiles);
129
- this._logger.debug("빌드 완료");
130
- return result;
131
- })(),
132
- (async () => {
133
- this._logger.debug("린트 시작");
134
- const result = await this._lintAsync(dirtySourceFiles);
135
- this._logger.debug("린트 완료");
136
- return result;
137
- })()
138
- ])
139
- ).mapMany();
140
- }
141
-
142
- protected async _lintAsync(dirtySourceFiles?: ts.SourceFile[]): Promise<ISdPackageBuildResult[]> {
143
- const linter = new ESLint({
144
- overrideConfig: {
145
- overrides: [
146
- {
147
- files: ["*.ts"],
148
- parserOptions: {
149
- program: this._program
150
- },
151
- settings: {
152
- "import/resolver": {
153
- typescript: {
154
- project: this.tsconfigFilePath
155
- }
156
- }
157
- }
158
- }
159
- ]
160
- }
161
- });
162
-
163
- const currDirtySourceFiles = dirtySourceFiles ?? this._builder!.getSourceFiles();
164
- const lintFilePaths = currDirtySourceFiles
165
- .map((item) => item.fileName)
166
- .filter((item) => (
167
- !item.includes("node_modules")
168
- && FsUtil.isChildPath(item, this.rootPath)
169
- && FsUtil.exists(item)
170
- && !FsUtil.isDirectory(item)
171
- ))
172
- .distinct();
173
- const lintResults = await linter.lintFiles(lintFilePaths);
174
-
175
- return lintResults.mapMany((report) => (
176
- report.messages.map((msg) => {
177
- const severity: "warning" | "error" = msg.severity === 1 ? "warning" : "error";
178
-
179
- return {
180
- filePath: report.filePath,
181
- severity,
182
- message: `${report.filePath}(${msg.line}, ${msg.column}): ${msg.ruleId ?? ""}: ${severity} ${msg.message}`
183
- };
184
- })
185
- ));
186
- }
187
-
188
- protected _getWatchPaths(): string[] {
189
- return Array.from(this._fileCache.entries())
190
- .mapMany((item) => [item[0], ...item[1].dependencyFilePaths ?? []])
191
- .map((item) => PathUtil.posix(path.dirname(item)))
192
- .distinct();
193
- }
194
-
195
- protected _deleteFileCaches(filePaths: string[]): void {
196
- for (const filePath of filePaths) {
197
- const cachedFileInfo = this._fileCache.get(filePath);
198
- if (cachedFileInfo) {
199
- if (!StringUtil.isNullOrEmpty(cachedFileInfo.jsFilePath)) {
200
- FsUtil.remove(cachedFileInfo.jsFilePath);
201
- }
202
- if (!StringUtil.isNullOrEmpty(cachedFileInfo.dtsFilePath)) {
203
- FsUtil.remove(cachedFileInfo.dtsFilePath);
204
- }
205
- }
206
- this._fileCache.delete(filePath);
207
- }
208
- }
209
-
210
- // eslint-disable-next-line @typescript-eslint/require-await
211
- protected async _runProgramAsync(dirtySourceFiles?: ts.SourceFile[]): Promise<ISdPackageBuildResult[]> {
212
- if (!this._builder) throw new NeverEntryError();
213
-
214
- const diagnostics = [
215
- ...this._builder.getOptionsDiagnostics(),
216
- ...this._builder.getGlobalDiagnostics()
217
- ];
218
-
219
- const currDirtySourceFiles = dirtySourceFiles ?? this._builder.getSourceFiles();
220
-
221
- for (const sourceFile of currDirtySourceFiles) {
222
- diagnostics.push(...[
223
- ...this._builder.getSyntacticDiagnostics(sourceFile),
224
- ...this._builder.getSemanticDiagnostics(sourceFile)
225
- ]);
226
- }
227
-
228
- if (!this.noEmit) {
229
- for (const sourceFile of currDirtySourceFiles) {
230
- this._builder.emit(sourceFile);
231
- }
232
- }
233
-
234
- return diagnostics.map((item) => SdTsDiagnosticUtil.convertDiagnosticsToResult(item)).filterExists();
235
- }
236
-
237
- protected _reloadProgram(watch: boolean): ts.SourceFile[] | undefined {
238
- const moduleResolutionCache = ts.createModuleResolutionCache(this.rootPath, (s) => s, this._parsedTsconfig.options);
239
- const cacheCompilerHost = this._createCacheCompilerHost(this._parsedTsconfig, moduleResolutionCache);
240
-
241
- this._program = ts.createProgram(
242
- this._parsedTsconfig.fileNames,
243
- this._parsedTsconfig.options,
244
- cacheCompilerHost,
245
- this._program
246
- );
247
-
248
- const baseGetSourceFiles = this._program.getSourceFiles;
249
- this._program.getSourceFiles = function (...parameters) {
250
- const files: readonly (ts.SourceFile & { version?: string })[] = baseGetSourceFiles(...parameters);
251
-
252
- for (const file of files) {
253
- if (file.version === undefined) {
254
- file.version = createHash("sha256").update(file.text).digest("hex");
255
- }
256
- }
257
-
258
- return files;
259
- };
260
-
261
- if (watch) {
262
- const builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
263
- this._program,
264
- cacheCompilerHost,
265
- this._builder as ts.EmitAndSemanticDiagnosticsBuilderProgram
266
- );
267
- this._builder = builder;
268
-
269
- const results: ts.SourceFile[] = [];
270
- while (true) {
271
- const result = builder.getSemanticDiagnosticsOfNextAffectedFile();
272
- if (result && "fileName" in result.affected) {
273
- results.push(result.affected);
274
- }
275
- if (!result) break;
276
- }
277
- return results;
278
- }
279
- else {
280
- this._builder = ts.createAbstractBuilder(this._program, cacheCompilerHost);
281
- return undefined;
282
- }
283
- }
284
-
285
- protected _createCacheCompilerHost(parsedTsconfig: ts.ParsedCommandLine, moduleResolutionCache: ts.ModuleResolutionCache): ts.CompilerHost {
286
- const compilerHost = ts.createCompilerHost(parsedTsconfig.options);
287
-
288
- const cacheCompilerHost = { ...compilerHost };
289
- cacheCompilerHost.fileExists = (fileName: string) => {
290
- const cache = this._fileCache.getOrCreate(PathUtil.posix(fileName), {});
291
- if (cache.exists === undefined) {
292
- cache.exists = compilerHost.fileExists.call(cacheCompilerHost, fileName);
293
- }
294
- return cache.exists;
295
- };
296
-
297
- cacheCompilerHost.getSourceFile = (fileName: string, languageVersion: ts.ScriptTarget) => {
298
- const cache = this._fileCache.getOrCreate(PathUtil.posix(fileName), {});
299
- if (!cache.sourceFile) {
300
- cache.sourceFile = compilerHost.getSourceFile.call(cacheCompilerHost, fileName, languageVersion);
301
- }
302
- if (!cache.dependencyFilePaths) {
303
- cache.dependencyFilePaths = this._getDependencyFilePaths(
304
- cache.sourceFile!,
305
- parsedTsconfig.options,
306
- compilerHost,
307
- moduleResolutionCache
308
- );
309
- }
310
- return cache.sourceFile;
311
- };
312
-
313
- cacheCompilerHost.writeFile = (fileName: string,
314
- data: string,
315
- writeByteOrderMark: boolean,
316
- onError?: (message: string) => void,
317
- sourceFiles?: readonly ts.SourceFile[]) => {
318
- if (sourceFiles && fileName.endsWith(".d.ts")) {
319
- sourceFiles.forEach((source) => {
320
- const cache = this._fileCache.getOrCreate(PathUtil.posix(source.fileName), {});
321
- if (StringUtil.isNullOrEmpty(cache.dtsFilePath)) {
322
- cache.dtsFilePath = fileName;
323
- compilerHost.writeFile.call(cacheCompilerHost, fileName, data, writeByteOrderMark, onError, sourceFiles);
324
- }
325
- });
326
- }
327
- else if (sourceFiles && fileName.endsWith(".js")) {
328
- sourceFiles.forEach((source) => {
329
- const cache = this._fileCache.getOrCreate(PathUtil.posix(source.fileName), {});
330
- if (StringUtil.isNullOrEmpty(cache.jsFilePath)) {
331
- cache.jsFilePath = fileName;
332
- compilerHost.writeFile.call(cacheCompilerHost, fileName, data, writeByteOrderMark, onError, sourceFiles);
333
- }
334
- });
335
- }
336
- else {
337
- compilerHost.writeFile.call(cacheCompilerHost, fileName, data, writeByteOrderMark, onError, sourceFiles);
338
- }
339
- };
340
-
341
- cacheCompilerHost.readFile = (fileName: string) => {
342
- const cache = this._fileCache.getOrCreate(PathUtil.posix(fileName), {});
343
- if (cache.content === undefined) {
344
- cache.content = compilerHost.readFile.call(cacheCompilerHost, fileName);
345
- }
346
- return cache.content;
347
- };
348
-
349
- cacheCompilerHost.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
350
- return moduleNames.map((moduleName) => {
351
- return ts.resolveModuleName(
352
- moduleName,
353
- containingFile,
354
- parsedTsconfig.options,
355
- compilerHost,
356
- moduleResolutionCache
357
- ).resolvedModule;
358
- });
359
- };
360
-
361
- return cacheCompilerHost;
362
- }
363
-
364
- protected _getDependencyFilePaths(sourceFile: ts.SourceFile,
365
- compilerOptions: ts.CompilerOptions,
366
- compilerHost: ts.CompilerHost,
367
- moduleResolutionCache: ts.ModuleResolutionCache): string[] {
368
- const result: string[] = [];
369
- ts.forEachChild(sourceFile, (node) => {
370
- if (ts.isImportDeclaration(node) || ts.isImportEqualsDeclaration(node) || ts.isExportDeclaration(node)) {
371
- const exp = this._getDependencyExpression(node);
372
- if (exp && ts.isStringLiteral(exp)) {
373
- const moduleName = exp.text;
374
-
375
- const resolvedModule = ts.resolveModuleName(
376
- moduleName,
377
- sourceFile.fileName,
378
- compilerOptions,
379
- compilerHost,
380
- moduleResolutionCache
381
- ).resolvedModule;
382
-
383
- if (resolvedModule) {
384
- result.push(PathUtil.posix(resolvedModule.resolvedFileName));
385
- }
386
- else if (moduleName.startsWith(".")) {
387
- result.push(...[
388
- PathUtil.posix(path.dirname(sourceFile.fileName), moduleName),
389
- PathUtil.posix(path.dirname(sourceFile.fileName), moduleName) + ".ts",
390
- PathUtil.posix(path.dirname(sourceFile.fileName), moduleName) + ".d.ts"
391
- ]);
392
- }
393
- }
394
- }
395
- });
396
- return result;
397
- }
398
-
399
- protected _getDependencyExpression(node: ts.Node): ts.Expression | undefined {
400
- if (ts.isImportDeclaration(node)) {
401
- return node.moduleSpecifier;
402
- }
403
- else if (ts.isImportEqualsDeclaration(node)) {
404
- const reference = node.moduleReference;
405
- if (ts.isExternalModuleReference(reference)) {
406
- return reference.expression;
407
- }
408
- }
409
- else if (ts.isExportDeclaration(node)) {
410
- return node.moduleSpecifier;
411
- }
412
-
413
- return undefined;
414
- }
415
- }
416
-
417
- export interface ITsBuildFileCache {
418
- exists?: boolean;
419
- sourceFile?: ts.SourceFile;
420
- dtsFilePath?: string;
421
- jsFilePath?: string;
422
- content?: string;
423
- dependencyFilePaths?: string[];
424
- }