@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.
- package/.eslintrc.js +1 -2
- package/dist-node/bin/sd-cli.js +25 -8
- package/dist-node/bin/sd-cli.js.map +1 -1
- package/dist-node/build-tools/SdCliIndexFileGenerator.js +51 -0
- package/dist-node/build-tools/SdCliIndexFileGenerator.js.map +1 -0
- package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js +621 -0
- package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js.map +1 -0
- package/dist-node/build-tools/metadata/SdAotMetadataReader.js +270 -0
- package/dist-node/build-tools/metadata/SdAotMetadataReader.js.map +1 -0
- package/dist-node/build-tools/metadata/SdIvyMetadataReader.js +101 -0
- package/dist-node/build-tools/metadata/SdIvyMetadataReader.js.map +1 -0
- package/dist-node/build-tools/metadata/SdMyMetadataReader.js +298 -0
- package/dist-node/build-tools/metadata/SdMyMetadataReader.js.map +1 -0
- package/dist-node/{build-tools → builders}/SdCliJavascriptLinter.js +1 -1
- package/dist-node/builders/SdCliJavascriptLinter.js.map +1 -0
- package/dist-node/{build-tools → builders}/SdCliNgClientBuilder.js +176 -102
- package/dist-node/builders/SdCliNgClientBuilder.js.map +1 -0
- package/dist-node/builders/SdCliNgLibraryBuilder.js +238 -0
- package/dist-node/builders/SdCliNgLibraryBuilder.js.map +1 -0
- package/dist-node/{build-tools → builders}/SdCliPublisher.js +0 -0
- package/dist-node/builders/SdCliPublisher.js.map +1 -0
- package/dist-node/{build-tools → builders}/SdCliServerBuilder.js +8 -6
- package/dist-node/builders/SdCliServerBuilder.js.map +1 -0
- package/dist-node/builders/SdCliTypescriptBuilder.js +304 -0
- package/dist-node/builders/SdCliTypescriptBuilder.js.map +1 -0
- package/dist-node/entry-points/SdCliLocalUpdater.js +9 -8
- package/dist-node/entry-points/SdCliLocalUpdater.js.map +1 -1
- package/dist-node/entry-points/SdCliProject.js +11 -9
- package/dist-node/entry-points/SdCliProject.js.map +1 -1
- package/dist-node/packages/SdCliClientPackage.js +12 -2
- package/dist-node/packages/SdCliClientPackage.js.map +1 -1
- package/dist-node/packages/SdCliLibraryPackage.js +17 -9
- package/dist-node/packages/SdCliLibraryPackage.js.map +1 -1
- package/dist-node/packages/SdCliServerPackage.js +2 -2
- package/dist-node/packages/SdCliServerPackage.js.map +1 -1
- package/dist-node/utils/SdCliFileCrypto.js +76 -0
- package/dist-node/utils/SdCliFileCrypto.js.map +1 -0
- package/dist-node/utils/SdProjectConfigUtil.js +1 -1
- package/dist-node/utils/SdProjectConfigUtil.js.map +1 -1
- package/dist-node/utils/SdWebpackUtil.js +12 -3
- package/dist-node/utils/SdWebpackUtil.js.map +1 -1
- package/dist-node/workers/lib-build-worker.js +7 -6
- package/dist-node/workers/lib-build-worker.js.map +1 -1
- package/dist-types/build-tools/SdCliIndexFileGenerator.d.ts +12 -0
- package/dist-types/build-tools/SdCliNgModuleFilesGenerator.d.ts +42 -0
- package/dist-types/build-tools/metadata/SdAotMetadataReader.d.ts +57 -0
- package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts +41 -0
- package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts +57 -0
- package/dist-types/{build-tools → builders}/SdCliJavascriptLinter.d.ts +0 -0
- package/dist-types/{build-tools → builders}/SdCliNgClientBuilder.d.ts +1 -1
- package/dist-types/builders/SdCliNgLibraryBuilder.d.ts +27 -0
- package/dist-types/{build-tools → builders}/SdCliPublisher.d.ts +0 -0
- package/dist-types/{build-tools → builders}/SdCliServerBuilder.d.ts +0 -0
- package/dist-types/builders/SdCliTypescriptBuilder.d.ts +46 -0
- package/dist-types/commons.d.ts +11 -3
- package/dist-types/packages/SdCliClientPackage.d.ts +1 -1
- package/dist-types/utils/SdCliFileCrypto.d.ts +7 -0
- package/dist-types/utils/SdWebpackUtil.d.ts +1 -0
- package/package.json +10 -7
- package/schema/schema.json +247 -0
- package/src/bin/sd-cli.ts +37 -14
- package/src/build-tools/SdCliIndexFileGenerator.ts +61 -0
- package/src/build-tools/SdCliNgModuleFilesGenerator.ts +837 -0
- package/src/build-tools/metadata/SdAotMetadataReader.ts +368 -0
- package/src/build-tools/metadata/SdIvyMetadataReader.ts +152 -0
- package/src/build-tools/metadata/SdMyMetadataReader.ts +379 -0
- package/src/{build-tools → builders}/SdCliJavascriptLinter.ts +1 -1
- package/src/{build-tools → builders}/SdCliNgClientBuilder.ts +209 -111
- package/src/builders/SdCliNgLibraryBuilder.ts +336 -0
- package/src/{build-tools → builders}/SdCliPublisher.ts +0 -0
- package/src/{build-tools → builders}/SdCliServerBuilder.ts +14 -8
- package/src/builders/SdCliTypescriptBuilder.ts +488 -0
- package/src/commons.ts +11 -3
- package/src/entry-points/SdCliLocalUpdater.ts +9 -8
- package/src/entry-points/SdCliProject.ts +12 -9
- package/src/packages/SdCliClientPackage.ts +14 -3
- package/src/packages/SdCliLibraryPackage.ts +19 -11
- package/src/packages/SdCliServerPackage.ts +2 -2
- package/src/utils/SdCliFileCrypto.ts +87 -0
- package/src/utils/SdCliUtils.ts +56 -0
- package/src/utils/SdProjectConfigUtil.ts +1 -1
- package/src/utils/SdWebpackUtil.ts +13 -3
- package/src/workers/lib-build-worker.ts +8 -7
- package/dist-node/build-tools/SdCliJavascriptLinter.js.map +0 -1
- package/dist-node/build-tools/SdCliNgClientBuilder.js.map +0 -1
- package/dist-node/build-tools/SdCliNgLibraryBuilder.js +0 -164
- package/dist-node/build-tools/SdCliNgLibraryBuilder.js.map +0 -1
- package/dist-node/build-tools/SdCliPublisher.js.map +0 -1
- package/dist-node/build-tools/SdCliServerBuilder.js.map +0 -1
- package/dist-node/build-tools/SdCliTypescriptBuilder.js +0 -316
- package/dist-node/build-tools/SdCliTypescriptBuilder.js.map +0 -1
- package/dist-node/build-tools/SdCliTypescriptIndexFileGenerator.js +0 -75
- package/dist-node/build-tools/SdCliTypescriptIndexFileGenerator.js.map +0 -1
- package/dist-types/build-tools/SdCliNgLibraryBuilder.d.ts +0 -23
- package/dist-types/build-tools/SdCliTypescriptBuilder.d.ts +0 -37
- package/dist-types/build-tools/SdCliTypescriptIndexFileGenerator.d.ts +0 -12
- package/src/build-tools/SdCliNgLibraryBuilder.ts +0 -225
- package/src/build-tools/SdCliTypescriptBuilder.ts +0 -424
- 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
|
-
}
|