@simplysm/sd-cli 12.8.20 → 12.8.22
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/entry/sd-cli-cordova.d.ts +30 -0
- package/dist/entry/sd-cli-cordova.js +307 -246
- package/dist/entry/sd-cli-cordova.js.map +1 -1
- package/dist/entry/sd-cli-project.d.ts +1 -1
- package/dist/entry/sd-cli-project.js +8 -9
- package/dist/entry/sd-cli-project.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/pkg-builders/client/sd-ng.bundler.d.ts +15 -1
- package/dist/pkg-builders/client/sd-ng.bundler.js +60 -70
- package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
- package/dist/pkg-builders/client/sd-ng.plugin-creator.js +49 -29
- package/dist/pkg-builders/client/sd-ng.plugin-creator.js.map +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.builder.js +7 -4
- package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
- package/dist/pkg-builders/server/sd-server.bundler.js +11 -10
- package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
- package/dist/ts-compiler/sd-ts-compiler.d.ts +25 -2
- package/dist/ts-compiler/sd-ts-compiler.js +306 -575
- package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
- package/dist/ts-compiler/sd-ts-dependency-analyzer.d.ts +6 -0
- package/dist/ts-compiler/sd-ts-dependency-analyzer.js +141 -0
- package/dist/ts-compiler/sd-ts-dependency-analyzer.js.map +1 -0
- package/dist/types/ts-compiler.types.d.ts +12 -7
- package/dist/types/worker.types.d.ts +13 -0
- package/dist/utils/sd-cli-performance-time.js +1 -1
- package/package.json +6 -8
- package/src/entry/sd-cli-cordova.ts +393 -280
- package/src/entry/sd-cli-project.ts +11 -23
- package/src/index.ts +1 -0
- package/src/pkg-builders/client/sd-ng.bundler.ts +67 -69
- package/src/pkg-builders/client/sd-ng.plugin-creator.ts +47 -27
- package/src/pkg-builders/lib/sd-ts-lib.builder.ts +14 -7
- package/src/pkg-builders/server/sd-server.bundler.ts +22 -12
- package/src/ts-compiler/sd-ts-compiler.ts +379 -704
- package/src/ts-compiler/sd-ts-dependency-analyzer.ts +185 -0
- package/src/types/ts-compiler.types.ts +11 -6
- package/src/types/worker.types.ts +7 -6
- package/src/utils/sd-cli-performance-time.ts +1 -1
|
@@ -16,26 +16,25 @@ import { SdCliPerformanceTimer } from "../utils/sd-cli-performance-time";
|
|
|
16
16
|
import { SdCliConvertMessageUtils } from "../utils/sd-cli-convert-message.utils";
|
|
17
17
|
import {
|
|
18
18
|
ISdTsCompilerResult,
|
|
19
|
-
IStylesheetBundlingResult,
|
|
20
19
|
SdTsCompilerOptions,
|
|
20
|
+
TStylesheetBundlingResult,
|
|
21
21
|
} from "../types/ts-compiler.types";
|
|
22
22
|
import { ISdBuildMessage } from "../types/build.types";
|
|
23
23
|
import {
|
|
24
24
|
createWorkerTransformer,
|
|
25
25
|
} from "@angular/build/src/tools/angular/transformers/web-worker-transformer";
|
|
26
26
|
import { ESLint } from "eslint";
|
|
27
|
+
import { SdTsDependencyAnalyzer } from "./sd-ts-dependency-analyzer";
|
|
27
28
|
|
|
28
29
|
export class SdTsCompiler {
|
|
29
|
-
|
|
30
|
+
private _logger = SdLogger.get(["simplysm", "sd-cli", "SdTsCompiler"]);
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
readonly #isForAngular: boolean;
|
|
32
|
+
private _isForAngular: boolean;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
readonly #emittedFilesCacheMap = new Map<
|
|
34
|
+
private _allDepCacheMap = new Map<TNormPath, Set<TNormPath>>();
|
|
35
|
+
private _revDepCacheMap = new Map<TNormPath, Set<TNormPath>>();
|
|
36
|
+
private _sourceFileCacheMap = new Map<TNormPath, ts.SourceFile>();
|
|
37
|
+
private _emittedFilesCacheMap = new Map<
|
|
39
38
|
TNormPath,
|
|
40
39
|
{
|
|
41
40
|
outAbsPath?: TNormPath;
|
|
@@ -43,73 +42,103 @@ export class SdTsCompiler {
|
|
|
43
42
|
}[]
|
|
44
43
|
>();
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
readonly #compilerHost: ts.CompilerHost | AngularCompilerHost;
|
|
45
|
+
private _stylesheetBundler: ComponentStylesheetBundler | undefined;
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
private _ngProgram: NgtscProgram | undefined;
|
|
48
|
+
private _program: ts.Program | undefined;
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
private _modifiedFileSet = new Set<TNormPath>();
|
|
51
|
+
private _affectedFileSet = new Set<TNormPath>();
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
private _watchFileSet = new Set<TNormPath>();
|
|
54
|
+
private _stylesheetBundlingResultMap = new Map<TNormPath, TStylesheetBundlingResult>();
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
readonly #distPath: TNormPath;
|
|
60
|
-
readonly #globalStyleFilePath?: TNormPath;
|
|
61
|
-
readonly #watchScopePaths: TNormPath[];
|
|
56
|
+
private _perf!: SdCliPerformanceTimer;
|
|
62
57
|
|
|
63
|
-
readonly
|
|
58
|
+
constructor(private readonly _opt: SdTsCompilerOptions) {
|
|
59
|
+
this._debug("초기화 중...");
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// #processWebWorker?: (workerFile: string, containingFile: string) => string;
|
|
70
|
-
|
|
71
|
-
constructor(opt: SdTsCompilerOptions) {
|
|
72
|
-
this.#pkgPath = opt.pkgPath;
|
|
73
|
-
this.#globalStyleFilePath = opt.globalStyleFilePath;
|
|
74
|
-
this.#isForBundle = opt.isForBundle;
|
|
75
|
-
this.#watchScopePaths = opt.watchScopePaths;
|
|
76
|
-
// this.#processWebWorker = opt.processWebWorker;
|
|
61
|
+
const tsconfigPath = path.resolve(this._opt.pkgPath, "tsconfig.json");
|
|
62
|
+
const tsconfig = FsUtils.readJson(tsconfigPath);
|
|
63
|
+
this._isForAngular = Boolean(tsconfig.angularCompilerOptions);
|
|
77
64
|
|
|
78
|
-
this
|
|
65
|
+
if (this._isForAngular) {
|
|
66
|
+
//-- stylesheetBundler
|
|
67
|
+
this._stylesheetBundler = new ComponentStylesheetBundler(
|
|
68
|
+
{
|
|
69
|
+
workspaceRoot: this._opt.pkgPath,
|
|
70
|
+
optimization: !this._opt.isDevMode,
|
|
71
|
+
inlineFonts: true,
|
|
72
|
+
preserveSymlinks: false,
|
|
73
|
+
sourcemap: this._opt.isDevMode ? "inline" : false,
|
|
74
|
+
outputNames: { bundles: "[name]", media: "media/[name]" },
|
|
75
|
+
includePaths: [],
|
|
76
|
+
externalDependencies: [],
|
|
77
|
+
target: transformSupportedBrowsersToTargets(browserslist(["Chrome > 78"])),
|
|
78
|
+
postcssConfiguration: {
|
|
79
|
+
plugins: [["css-has-pseudo"]],
|
|
80
|
+
},
|
|
81
|
+
tailwindConfiguration: undefined,
|
|
82
|
+
cacheOptions: {
|
|
83
|
+
enabled: true,
|
|
84
|
+
path: ".cache/angular",
|
|
85
|
+
basePath: ".cache",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"scss",
|
|
89
|
+
this._opt.isDevMode,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
79
93
|
|
|
80
|
-
|
|
94
|
+
private _parseTsConfig(): ITsConfigInfo {
|
|
95
|
+
const config = this._loadTsConfig();
|
|
96
|
+
const compilerHost = this._createCompilerHost(config.options);
|
|
97
|
+
return {
|
|
98
|
+
...config,
|
|
99
|
+
compilerHost,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
81
102
|
|
|
82
|
-
|
|
103
|
+
private _loadTsConfig() {
|
|
104
|
+
const tsconfigPath = path.resolve(this._opt.pkgPath, "tsconfig.json");
|
|
83
105
|
const tsconfig = FsUtils.readJson(tsconfigPath);
|
|
84
|
-
|
|
85
|
-
this.#parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, opt.pkgPath, {
|
|
106
|
+
const parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._opt.pkgPath, {
|
|
86
107
|
...tsconfig.angularCompilerOptions,
|
|
87
|
-
...
|
|
108
|
+
...this._opt.additionalOptions,
|
|
88
109
|
});
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
|
|
111
|
+
const distPath = PathUtils.norm(parsedTsconfig.options.outDir ?? path.resolve(
|
|
112
|
+
this._opt.pkgPath,
|
|
92
113
|
"dist",
|
|
93
114
|
));
|
|
94
115
|
|
|
95
|
-
|
|
116
|
+
return {
|
|
117
|
+
fileNames: parsedTsconfig.fileNames,
|
|
118
|
+
options: parsedTsconfig.options,
|
|
119
|
+
distPath: distPath,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
96
122
|
|
|
97
|
-
|
|
123
|
+
private _createCompilerHost(compilerOptions: ts.CompilerOptions) {
|
|
124
|
+
const compilerHost = ts.createCompilerHost(compilerOptions);
|
|
98
125
|
|
|
99
|
-
const baseGetSourceFile =
|
|
100
|
-
|
|
126
|
+
const baseGetSourceFile = compilerHost.getSourceFile;
|
|
127
|
+
compilerHost.getSourceFile = (
|
|
101
128
|
fileName: string,
|
|
102
129
|
languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions,
|
|
103
130
|
onError?: ((message: string) => void) | undefined,
|
|
104
131
|
shouldCreateNewSourceFile?: boolean,
|
|
105
132
|
...args
|
|
106
133
|
): ts.SourceFile | undefined => {
|
|
107
|
-
|
|
108
|
-
|
|
134
|
+
const fileNPath = PathUtils.norm(fileName);
|
|
135
|
+
|
|
136
|
+
if (!shouldCreateNewSourceFile && this._sourceFileCacheMap.has(fileNPath)) {
|
|
137
|
+
return this._sourceFileCacheMap.get(fileNPath);
|
|
109
138
|
}
|
|
110
139
|
|
|
111
140
|
const sf: ts.SourceFile | undefined = baseGetSourceFile.call(
|
|
112
|
-
|
|
141
|
+
compilerHost,
|
|
113
142
|
fileName,
|
|
114
143
|
languageVersionOrOptions,
|
|
115
144
|
onError,
|
|
@@ -118,55 +147,27 @@ export class SdTsCompiler {
|
|
|
118
147
|
);
|
|
119
148
|
|
|
120
149
|
if (sf) {
|
|
121
|
-
this
|
|
150
|
+
this._sourceFileCacheMap.set(fileNPath, sf);
|
|
122
151
|
}
|
|
123
152
|
else {
|
|
124
|
-
this
|
|
153
|
+
this._sourceFileCacheMap.delete(fileNPath);
|
|
125
154
|
}
|
|
126
155
|
|
|
127
156
|
return sf;
|
|
128
157
|
};
|
|
129
158
|
|
|
130
|
-
const baseReadFile =
|
|
131
|
-
|
|
132
|
-
this
|
|
133
|
-
return baseReadFile.call(
|
|
159
|
+
const baseReadFile = compilerHost.readFile;
|
|
160
|
+
compilerHost.readFile = (fileName) => {
|
|
161
|
+
this._watchFileSet.add(PathUtils.norm(fileName));
|
|
162
|
+
return baseReadFile.call(compilerHost, fileName);
|
|
134
163
|
};
|
|
135
164
|
|
|
136
|
-
if (this
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
workspaceRoot: opt.pkgPath,
|
|
141
|
-
optimization: !opt.isDevMode,
|
|
142
|
-
inlineFonts: true,
|
|
143
|
-
preserveSymlinks: false,
|
|
144
|
-
sourcemap: opt.isDevMode ? "inline" : false,
|
|
145
|
-
outputNames: { bundles: "[name]", media: "media/[name]" },
|
|
146
|
-
includePaths: [],
|
|
147
|
-
externalDependencies: [],
|
|
148
|
-
target: transformSupportedBrowsersToTargets(browserslist(["Chrome > 78"])),
|
|
149
|
-
postcssConfiguration: {
|
|
150
|
-
plugins: [["css-has-pseudo"]],
|
|
151
|
-
},
|
|
152
|
-
tailwindConfiguration: undefined,
|
|
153
|
-
cacheOptions: {
|
|
154
|
-
enabled: true,
|
|
155
|
-
path: ".cache/angular",
|
|
156
|
-
basePath: ".cache",
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
"scss",
|
|
160
|
-
opt.isDevMode,
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
//-- compilerHost
|
|
164
|
-
|
|
165
|
-
(this.#compilerHost as AngularCompilerHost).readResource = (fileName: string) => {
|
|
166
|
-
return this.#compilerHost.readFile(fileName) ?? "";
|
|
165
|
+
if (this._isForAngular) {
|
|
166
|
+
(compilerHost as AngularCompilerHost).readResource = (fileName: string) => {
|
|
167
|
+
return compilerHost.readFile(fileName) ?? "";
|
|
167
168
|
};
|
|
168
169
|
|
|
169
|
-
(
|
|
170
|
+
(compilerHost as AngularCompilerHost).transformResource = async (
|
|
170
171
|
data: string,
|
|
171
172
|
context: {
|
|
172
173
|
type: string;
|
|
@@ -178,69 +179,88 @@ export class SdTsCompiler {
|
|
|
178
179
|
return null;
|
|
179
180
|
}
|
|
180
181
|
|
|
181
|
-
const
|
|
182
|
+
const stylesheetBundlingResult = await this._bundleStylesheetAsync(
|
|
182
183
|
data,
|
|
183
184
|
PathUtils.norm(context.containingFile),
|
|
184
185
|
context.resourceFile != null ? PathUtils.norm(context.resourceFile) : undefined,
|
|
185
186
|
);
|
|
186
187
|
|
|
187
|
-
return StringUtils.isNullOrEmpty(contents)
|
|
188
|
+
return StringUtils.isNullOrEmpty(stylesheetBundlingResult.contents)
|
|
189
|
+
? null
|
|
190
|
+
: { content: stylesheetBundlingResult.contents };
|
|
188
191
|
};
|
|
189
192
|
|
|
190
|
-
(
|
|
191
|
-
return new Set(Array.from(this
|
|
193
|
+
(compilerHost as AngularCompilerHost).getModifiedResourceFiles = () => {
|
|
194
|
+
return new Set(Array.from(this._modifiedFileSet).map((item) => PathUtils.posix(item)));
|
|
192
195
|
};
|
|
193
196
|
}
|
|
197
|
+
|
|
198
|
+
return compilerHost;
|
|
194
199
|
}
|
|
195
200
|
|
|
196
|
-
async
|
|
201
|
+
private async _bundleStylesheetAsync(
|
|
197
202
|
data: string,
|
|
198
203
|
containingFile: TNormPath,
|
|
199
204
|
resourceFile: TNormPath | null = null,
|
|
200
|
-
) {
|
|
205
|
+
): Promise<TStylesheetBundlingResult> {
|
|
201
206
|
// containingFile: 포함된 파일 (.ts)
|
|
202
207
|
// resourceFile: 외부 리소스 파일 (styleUrls로 입력하지 않고 styles에 직접 입력한 경우 null)
|
|
203
208
|
// referencedFiles: import한 외부 scss 파일 혹은 woff파일등 외부 파일
|
|
204
209
|
|
|
205
210
|
// this.#debug(`bundle stylesheet...(${containingFile}, ${resourceFile})`);
|
|
206
211
|
|
|
207
|
-
return await this
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
return await this._perf.run("스타일 번들링", async () => {
|
|
213
|
+
const fileNPath = PathUtils.norm(resourceFile ?? containingFile);
|
|
214
|
+
if (this._stylesheetBundlingResultMap.has(fileNPath)) {
|
|
215
|
+
return this._stylesheetBundlingResultMap.get(fileNPath)!;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const result =
|
|
220
|
+
resourceFile != null
|
|
221
|
+
? await this._stylesheetBundler!.bundleFile(resourceFile)
|
|
222
|
+
: await this._stylesheetBundler!.bundleInline(data, containingFile, "scss");
|
|
223
|
+
|
|
224
|
+
if (result.referencedFiles) {
|
|
225
|
+
for (const referencedFile of result.referencedFiles) {
|
|
226
|
+
const depCacheSet = this._revDepCacheMap.getOrCreate(
|
|
227
|
+
PathUtils.norm(referencedFile),
|
|
228
|
+
new Set<TNormPath>(),
|
|
229
|
+
);
|
|
230
|
+
depCacheSet.add(fileNPath);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
this._watchFileSet.adds(
|
|
234
|
+
...Array.from(result.referencedFiles.values())
|
|
235
|
+
.map((item) => PathUtils.norm(item)),
|
|
218
236
|
);
|
|
219
|
-
depCacheSet.add(resourceFile ?? containingFile);
|
|
220
237
|
}
|
|
221
238
|
|
|
222
|
-
this
|
|
223
|
-
...Array.from(stylesheetResult.referencedFiles.values())
|
|
224
|
-
.map((item) => PathUtils.norm(item)),
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
this.#stylesheetBundlingResultMap.set(PathUtils.norm(resourceFile ?? containingFile), {
|
|
229
|
-
outputFiles: stylesheetResult.errors == null ? stylesheetResult.outputFiles : undefined,
|
|
230
|
-
metafile: stylesheetResult.errors == null ? stylesheetResult.metafile : undefined,
|
|
231
|
-
errors: stylesheetResult.errors,
|
|
232
|
-
warnings: stylesheetResult.warnings,
|
|
233
|
-
});
|
|
239
|
+
this._stylesheetBundlingResultMap.set(fileNPath, result);
|
|
234
240
|
|
|
235
|
-
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
const result = {
|
|
245
|
+
errors: [
|
|
246
|
+
{
|
|
247
|
+
text: `스타일 번들링 실패: ${err.message ?? "알 수 없는 오류"}`,
|
|
248
|
+
location: { file: containingFile },
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
warnings: [],
|
|
252
|
+
};
|
|
253
|
+
this._stylesheetBundlingResultMap.set(fileNPath, result);
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
236
256
|
});
|
|
237
257
|
}
|
|
238
258
|
|
|
239
|
-
async compileAsync(modifiedFileSet: Set<TNormPath>): Promise<ISdTsCompilerResult> {
|
|
240
|
-
this
|
|
259
|
+
public async compileAsync(modifiedFileSet: Set<TNormPath>): Promise<ISdTsCompilerResult> {
|
|
260
|
+
this._perf = new SdCliPerformanceTimer("esbuild compile");
|
|
241
261
|
|
|
242
|
-
this
|
|
243
|
-
this
|
|
262
|
+
this._modifiedFileSet = new Set(modifiedFileSet);
|
|
263
|
+
this._affectedFileSet = new Set<TNormPath>();
|
|
244
264
|
|
|
245
265
|
/*for (const mod of modifiedFileSet) {
|
|
246
266
|
const workerImporters = this.#workerRevDependencyCacheMap.get(mod);
|
|
@@ -251,11 +271,18 @@ export class SdTsCompiler {
|
|
|
251
271
|
}
|
|
252
272
|
}*/
|
|
253
273
|
|
|
254
|
-
const
|
|
274
|
+
const tsconf = this._parseTsConfig();
|
|
255
275
|
|
|
256
|
-
const
|
|
276
|
+
const prepareResult = await this._prepareAsync(tsconf);
|
|
257
277
|
|
|
258
|
-
|
|
278
|
+
const [buildResult, lintResults] = await Promise.all([
|
|
279
|
+
this._buildAsync(tsconf),
|
|
280
|
+
this._lintAsync(),
|
|
281
|
+
]);
|
|
282
|
+
|
|
283
|
+
this._debug(`빌드 완료됨`, this._perf.toString());
|
|
284
|
+
this._debug(`영향 받은 파일: ${this._affectedFileSet.size}개`);
|
|
285
|
+
this._debug(`감시 중인 파일: ${this._watchFileSet.size}개`);
|
|
259
286
|
|
|
260
287
|
return {
|
|
261
288
|
messages: [
|
|
@@ -263,210 +290,192 @@ export class SdTsCompiler {
|
|
|
263
290
|
...SdCliConvertMessageUtils.convertToBuildMessagesFromTsDiag(buildResult.diagnostics),
|
|
264
291
|
...SdCliConvertMessageUtils.convertToBuildMessagesFromEslint(lintResults),
|
|
265
292
|
],
|
|
266
|
-
watchFileSet: this
|
|
267
|
-
affectedFileSet: this
|
|
268
|
-
stylesheetBundlingResultMap: this
|
|
269
|
-
emittedFilesCacheMap: this
|
|
293
|
+
watchFileSet: this._watchFileSet,
|
|
294
|
+
affectedFileSet: this._affectedFileSet,
|
|
295
|
+
stylesheetBundlingResultMap: this._stylesheetBundlingResultMap,
|
|
296
|
+
emittedFilesCacheMap: this._emittedFilesCacheMap,
|
|
270
297
|
emitFileSet: buildResult.emitFileSet,
|
|
271
298
|
};
|
|
272
299
|
}
|
|
273
300
|
|
|
274
|
-
async
|
|
275
|
-
if (this
|
|
276
|
-
this
|
|
301
|
+
private async _prepareAsync(tsconf: ITsConfigInfo) {
|
|
302
|
+
if (this._modifiedFileSet.size !== 0) {
|
|
303
|
+
this._debug(`영향 받은 파일 추적 중... (구 의존성)`);
|
|
304
|
+
|
|
305
|
+
this._perf.run("영향 받은 파일 추적", () => {
|
|
306
|
+
for (const modifiedFile of this._modifiedFileSet) {
|
|
307
|
+
this._affectedFileSet.add(modifiedFile);
|
|
308
|
+
|
|
309
|
+
this._affectedFileSet.adds(...(this._revDepCacheMap.get(modifiedFile) ?? []));
|
|
277
310
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
311
|
+
// .d.ts → .js 대응
|
|
312
|
+
if (modifiedFile.endsWith(".d.ts")) {
|
|
313
|
+
const jsEquivalent = PathUtils.norm(modifiedFile.replace(/\.d\.ts$/, ".js"));
|
|
314
|
+
this._affectedFileSet.add(jsEquivalent);
|
|
315
|
+
}
|
|
283
316
|
}
|
|
284
317
|
});
|
|
285
318
|
|
|
286
|
-
this
|
|
319
|
+
this._debug(`캐시 무효화 및 초기화 중...`);
|
|
320
|
+
|
|
321
|
+
this._perf.run("캐시 무효화 및 초기화", () => {
|
|
322
|
+
this._stylesheetBundler?.invalidate(this._affectedFileSet);
|
|
323
|
+
|
|
324
|
+
const toDeleteSet = new Set<TNormPath>();
|
|
287
325
|
|
|
288
|
-
|
|
289
|
-
|
|
326
|
+
// 초기: 명시적으로 수정된 파일들
|
|
327
|
+
for (const file of this._affectedFileSet) {
|
|
328
|
+
toDeleteSet.add(file);
|
|
290
329
|
|
|
291
|
-
|
|
292
|
-
this
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
330
|
+
// 역방향으로 영향을 받는 파일들도 포함
|
|
331
|
+
const dependents = this._revDepCacheMap.get(file);
|
|
332
|
+
if (dependents) {
|
|
333
|
+
for (const dep of dependents) {
|
|
334
|
+
toDeleteSet.add(dep);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
for (const toDeleteFile of toDeleteSet) {
|
|
340
|
+
this._emittedFilesCacheMap.delete(toDeleteFile);
|
|
341
|
+
this._sourceFileCacheMap.delete(toDeleteFile);
|
|
342
|
+
this._stylesheetBundlingResultMap.delete(toDeleteFile);
|
|
343
|
+
this._watchFileSet.delete(toDeleteFile);
|
|
344
|
+
this._allDepCacheMap.delete(toDeleteFile);
|
|
345
|
+
this._revDepCacheMap.delete(toDeleteFile);
|
|
296
346
|
}
|
|
297
347
|
|
|
298
|
-
this
|
|
299
|
-
|
|
348
|
+
for (const [key, deps] of this._revDepCacheMap) {
|
|
349
|
+
for (const file of toDeleteSet) {
|
|
350
|
+
deps.delete(file);
|
|
351
|
+
}
|
|
352
|
+
if (deps.size === 0) {
|
|
353
|
+
this._revDepCacheMap.delete(key);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
300
356
|
});
|
|
301
357
|
}
|
|
302
358
|
|
|
303
|
-
this
|
|
359
|
+
this._debug(`ts.Program 생성 중...`);
|
|
304
360
|
|
|
305
|
-
this
|
|
306
|
-
if (this
|
|
307
|
-
this
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this
|
|
361
|
+
this._perf.run("ts.Program 생성", () => {
|
|
362
|
+
if (this._isForAngular) {
|
|
363
|
+
this._ngProgram = new NgtscProgram(
|
|
364
|
+
tsconf.fileNames,
|
|
365
|
+
tsconf.options,
|
|
366
|
+
tsconf.compilerHost,
|
|
367
|
+
this._ngProgram,
|
|
312
368
|
);
|
|
313
|
-
this
|
|
369
|
+
this._program = this._ngProgram.getTsProgram();
|
|
314
370
|
}
|
|
315
371
|
else {
|
|
316
|
-
this
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
this
|
|
372
|
+
this._program = ts.createProgram(
|
|
373
|
+
tsconf.fileNames,
|
|
374
|
+
tsconf.options,
|
|
375
|
+
tsconf.compilerHost,
|
|
376
|
+
this._program,
|
|
321
377
|
);
|
|
322
378
|
}
|
|
323
379
|
});
|
|
324
380
|
|
|
325
|
-
if (this
|
|
326
|
-
await this
|
|
327
|
-
await this
|
|
381
|
+
if (this._ngProgram) {
|
|
382
|
+
await this._perf.run("Angular 템플릿 분석", async () => {
|
|
383
|
+
await this._ngProgram!.compiler.analyzeAsync();
|
|
328
384
|
});
|
|
329
385
|
}
|
|
330
386
|
|
|
331
|
-
|
|
332
|
-
if (sf.fileName.endsWith(".ngtypecheck.ts")) {
|
|
333
|
-
const orgFileName = sf.fileName.slice(0, -15) + ".ts";
|
|
334
|
-
return this.#program!.getSourceFile(orgFileName);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return sf;
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
const sourceFileSet = new Set(
|
|
341
|
-
this.#program!.getSourceFiles()
|
|
342
|
-
.map((sf) => getOrgSourceFile(sf))
|
|
343
|
-
.filterExists(),
|
|
344
|
-
);
|
|
345
|
-
|
|
346
|
-
this.#debug(`get new deps...`);
|
|
387
|
+
this._debug(`새 의존성 분석 중...`);
|
|
347
388
|
|
|
348
389
|
const messages: ISdBuildMessage[] = [];
|
|
390
|
+
this._perf.run("새 의존성 분석", () => {
|
|
391
|
+
const analysed = SdTsDependencyAnalyzer.analyze(
|
|
392
|
+
this._program!,
|
|
393
|
+
tsconf.compilerHost,
|
|
394
|
+
this._opt.watchScopePaths,
|
|
395
|
+
this._allDepCacheMap,
|
|
396
|
+
);
|
|
397
|
+
messages.push(...analysed);
|
|
349
398
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
{
|
|
354
|
-
fileName: TNormPath;
|
|
355
|
-
importName: string;
|
|
356
|
-
exportName?: string;
|
|
357
|
-
}[]
|
|
358
|
-
>();
|
|
359
|
-
for (const sf of sourceFileSet) {
|
|
360
|
-
if (!this.#watchScopePaths.some((scopePath) => PathUtils.isChildPath(
|
|
361
|
-
sf.fileName,
|
|
362
|
-
scopePath,
|
|
363
|
-
))) {
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const refs = this.#findDeps(sf);
|
|
368
|
-
messages.push(...refs.filter((item) => "severity" in item));
|
|
369
|
-
depMap.set(
|
|
370
|
-
PathUtils.norm(sf.fileName),
|
|
371
|
-
refs
|
|
372
|
-
.filter((item) => "fileName" in item)
|
|
373
|
-
.filter((item) =>
|
|
374
|
-
this.#watchScopePaths.some((scopePath) => PathUtils.isChildPath(
|
|
375
|
-
item.fileName,
|
|
376
|
-
scopePath,
|
|
377
|
-
)),
|
|
378
|
-
),
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const allDepMap = new Map<TNormPath, Set<TNormPath>>();
|
|
383
|
-
const getAllDeps = (fileName: TNormPath, prevSet?: Set<TNormPath>) => {
|
|
384
|
-
if (allDepMap.has(fileName)) {
|
|
385
|
-
return allDepMap.get(fileName)!;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const result = new Set<TNormPath>();
|
|
389
|
-
|
|
390
|
-
const deps = depMap.get(fileName) ?? [];
|
|
391
|
-
result.adds(...deps.map((item) => item.fileName));
|
|
399
|
+
for (const fileNPath of this._allDepCacheMap.keys()) {
|
|
400
|
+
// const filePath = PathUtils.norm(sf.fileName);
|
|
401
|
+
const deps = this._allDepCacheMap.get(fileNPath)!;
|
|
392
402
|
|
|
393
403
|
for (const dep of deps) {
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
if (dep.importName === "*") {
|
|
397
|
-
for (const targetRefItem of targetDeps.filter((item) => item.exportName != null)) {
|
|
398
|
-
if (prevSet?.has(targetRefItem.fileName)) continue;
|
|
399
|
-
|
|
400
|
-
result.add(targetRefItem.fileName);
|
|
401
|
-
result.adds(...getAllDeps(
|
|
402
|
-
targetRefItem.fileName,
|
|
403
|
-
new Set<TNormPath>(prevSet).adds(...result),
|
|
404
|
-
));
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
for (const targetRefItem of targetDeps.filter((item) => item.exportName
|
|
409
|
-
=== dep.importName)) {
|
|
410
|
-
if (prevSet?.has(targetRefItem.fileName)) continue;
|
|
411
|
-
|
|
412
|
-
result.add(targetRefItem.fileName);
|
|
413
|
-
result.adds(...getAllDeps(
|
|
414
|
-
targetRefItem.fileName,
|
|
415
|
-
new Set<TNormPath>(prevSet).adds(...result),
|
|
416
|
-
));
|
|
417
|
-
}
|
|
418
|
-
}
|
|
404
|
+
const depCache = this._revDepCacheMap.getOrCreate(dep, new Set<TNormPath>());
|
|
405
|
+
depCache.add(fileNPath);
|
|
419
406
|
}
|
|
420
407
|
|
|
421
|
-
|
|
422
|
-
|
|
408
|
+
if (this._ngProgram) {
|
|
409
|
+
const sf = this._program!.getSourceFile(fileNPath)!;
|
|
423
410
|
|
|
424
|
-
|
|
425
|
-
const deps = getAllDeps(PathUtils.norm(sf.fileName));
|
|
426
|
-
allDepMap.set(PathUtils.norm(sf.fileName), deps);
|
|
427
|
-
|
|
428
|
-
for (const dep of getAllDeps(PathUtils.norm(sf.fileName))) {
|
|
429
|
-
const depCache = this.#revDependencyCacheMap.getOrCreate(dep, new Set<TNormPath>());
|
|
430
|
-
depCache.add(PathUtils.norm(sf.fileName));
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (this.#ngProgram) {
|
|
434
|
-
if (this.#ngProgram.compiler.ignoreForEmit.has(sf)) {
|
|
411
|
+
if (this._ngProgram.compiler.ignoreForEmit.has(sf)) {
|
|
435
412
|
continue;
|
|
436
413
|
}
|
|
437
414
|
|
|
438
|
-
for (const dep of this
|
|
439
|
-
const ref = this
|
|
415
|
+
for (const dep of this._ngProgram.compiler.getResourceDependencies(sf)) {
|
|
416
|
+
const ref = this._revDepCacheMap.getOrCreate(
|
|
440
417
|
PathUtils.norm(dep),
|
|
441
418
|
new Set<TNormPath>(),
|
|
442
419
|
);
|
|
443
|
-
ref.add(
|
|
420
|
+
ref.add(fileNPath);
|
|
444
421
|
}
|
|
445
422
|
}
|
|
446
423
|
}
|
|
447
424
|
});
|
|
448
425
|
|
|
449
|
-
if (this
|
|
450
|
-
this
|
|
426
|
+
if (this._modifiedFileSet.size === 0) {
|
|
427
|
+
this._debug(`영향 받은 파일 추가 중... (새 의존성)`);
|
|
451
428
|
|
|
452
|
-
this
|
|
453
|
-
for (const
|
|
454
|
-
if (!this
|
|
455
|
-
|
|
429
|
+
this._perf.run("영향 받은 파일 추가 중 (새 의존성)", () => {
|
|
430
|
+
for (const fileNPath of this._allDepCacheMap.keys()) {
|
|
431
|
+
if (!this._opt.watchScopePaths.some((scopePath) => PathUtils.isChildPath(
|
|
432
|
+
fileNPath,
|
|
456
433
|
scopePath,
|
|
457
434
|
))) {
|
|
458
435
|
continue;
|
|
459
436
|
}
|
|
460
437
|
|
|
461
|
-
this
|
|
438
|
+
this._affectedFileSet.add(fileNPath);
|
|
462
439
|
}
|
|
463
440
|
});
|
|
464
441
|
}
|
|
465
442
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
443
|
+
/**
|
|
444
|
+
* AI가 넣으라고해서 넣었지만 이유는 잘 모르겠음.
|
|
445
|
+
* AI측의 설명은 아래와 같음:
|
|
446
|
+
*
|
|
447
|
+
* 변경된 파일이 .d.ts일 경우, 타입 정보만을 가져다 쓰는 다수의 .ts 파일들이
|
|
448
|
+
* 직접적으로 import하고 있어도 revDepMap에는 기록되지 않을 수 있음.
|
|
449
|
+
*
|
|
450
|
+
* 따라서 .d.ts 파일을 참조하는 모든 파일을 allDepCacheMap에서 역추적하여
|
|
451
|
+
* 간접 영향 파일들을 정확하게 affectedFileSet에 포함시켜야 함.
|
|
452
|
+
*
|
|
453
|
+
* 이 블록은 정확도 보완을 위한 보증 로직이며, 특히 초기 빌드 또는 watch 시 의존성 누락을 방지함.
|
|
454
|
+
*/
|
|
455
|
+
for (const modifiedFile of this._modifiedFileSet) {
|
|
456
|
+
// 신규 추가된 파일이 누락되지 않도록 추가하라고 하여 넣음
|
|
457
|
+
if (
|
|
458
|
+
!this._revDepCacheMap.has(modifiedFile) &&
|
|
459
|
+
!this._allDepCacheMap.has(modifiedFile) &&
|
|
460
|
+
this._program!.getSourceFile(modifiedFile)
|
|
461
|
+
) {
|
|
462
|
+
this._affectedFileSet.add(modifiedFile);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// AI가 넣으라 한부분에 대한 설명은 여기서부터임
|
|
466
|
+
if (!modifiedFile.endsWith(".d.ts")) continue;
|
|
467
|
+
|
|
468
|
+
for (const [importer, deps] of this._allDepCacheMap) {
|
|
469
|
+
if (deps.has(modifiedFile)) {
|
|
470
|
+
this._affectedFileSet.add(importer);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
for (const dep of this._revDepCacheMap.keys()) {
|
|
476
|
+
if (this._modifiedFileSet.has(dep)) {
|
|
477
|
+
this._affectedFileSet.adds(
|
|
478
|
+
...Array.from(this._revDepCacheMap.get(dep)!).mapMany((item) =>
|
|
470
479
|
[
|
|
471
480
|
item,
|
|
472
481
|
// .d.ts면 .js파일도 affected에 추가
|
|
@@ -478,22 +487,8 @@ export class SdTsCompiler {
|
|
|
478
487
|
|
|
479
488
|
// dep이 emit된적이 없으면 affected에 추가해야함.
|
|
480
489
|
// dep파일이 추가된후 기존 파일에서 import하면 dep파일이 affected에 포함이 안되는 현상 때문
|
|
481
|
-
if (!this
|
|
482
|
-
this
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
if (this.#ngProgram) {
|
|
487
|
-
for (const dep of this.#resourceDependencyCacheMap.keys()) {
|
|
488
|
-
if (this.#modifiedFileSet.has(dep)) {
|
|
489
|
-
this.#affectedFileSet.adds(...this.#resourceDependencyCacheMap.get(dep)!);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// dep이 emit된적이 없으면 affected에 추가해야함.
|
|
493
|
-
// dep파일이 추가된후 기존 파일에서 import하면 dep파일이 affected에 포함이 안되는 현상 때문
|
|
494
|
-
if (!this.#emittedFilesCacheMap.has(dep)) {
|
|
495
|
-
this.#affectedFileSet.add(dep);
|
|
496
|
-
}
|
|
490
|
+
if (!this._emittedFilesCacheMap.has(dep)) {
|
|
491
|
+
this._affectedFileSet.add(dep);
|
|
497
492
|
}
|
|
498
493
|
}
|
|
499
494
|
|
|
@@ -502,9 +497,9 @@ export class SdTsCompiler {
|
|
|
502
497
|
};
|
|
503
498
|
}
|
|
504
499
|
|
|
505
|
-
async
|
|
506
|
-
const lintFilePaths = Array.from(this
|
|
507
|
-
.filter((item) => PathUtils.isChildPath(item, this
|
|
500
|
+
private async _lintAsync() {
|
|
501
|
+
const lintFilePaths = Array.from(this._affectedFileSet)
|
|
502
|
+
.filter((item) => PathUtils.isChildPath(item, this._opt.pkgPath))
|
|
508
503
|
.filter((item) => (
|
|
509
504
|
(!item.endsWith(".d.ts") && item.endsWith(".ts")) ||
|
|
510
505
|
item.endsWith(".js")
|
|
@@ -516,14 +511,14 @@ export class SdTsCompiler {
|
|
|
516
511
|
}
|
|
517
512
|
|
|
518
513
|
const linter = new ESLint({
|
|
519
|
-
cwd: this
|
|
514
|
+
cwd: this._opt.pkgPath,
|
|
520
515
|
cache: false,
|
|
521
516
|
overrideConfig: {
|
|
522
517
|
languageOptions: {
|
|
523
518
|
parserOptions: {
|
|
524
519
|
// parser: tseslint.parser,
|
|
525
520
|
project: null,
|
|
526
|
-
programs: [this
|
|
521
|
+
programs: [this._program],
|
|
527
522
|
},
|
|
528
523
|
},
|
|
529
524
|
},
|
|
@@ -538,57 +533,52 @@ export class SdTsCompiler {
|
|
|
538
533
|
// ]);
|
|
539
534
|
}
|
|
540
535
|
|
|
541
|
-
async
|
|
536
|
+
private async _buildAsync(tsconf: ITsConfigInfo) {
|
|
542
537
|
const emitFileSet = new Set<TNormPath>();
|
|
543
538
|
const diagnostics: ts.Diagnostic[] = [];
|
|
544
539
|
|
|
545
|
-
this
|
|
540
|
+
this._debug(`프로그램 진단 수집 중...`);
|
|
546
541
|
|
|
547
|
-
this
|
|
542
|
+
this._perf.run("프로그램 진단 수집", () => {
|
|
548
543
|
diagnostics.push(
|
|
549
|
-
...this
|
|
550
|
-
...this
|
|
551
|
-
...this
|
|
544
|
+
...this._program!.getConfigFileParsingDiagnostics(),
|
|
545
|
+
...this._program!.getOptionsDiagnostics(),
|
|
546
|
+
...this._program!.getGlobalDiagnostics(),
|
|
552
547
|
);
|
|
553
548
|
|
|
554
|
-
if (this
|
|
555
|
-
diagnostics.push(...this
|
|
549
|
+
if (this._ngProgram) {
|
|
550
|
+
diagnostics.push(...this._ngProgram.compiler.getOptionDiagnostics());
|
|
556
551
|
}
|
|
557
552
|
});
|
|
558
553
|
|
|
559
|
-
this
|
|
560
|
-
|
|
561
|
-
for (const affectedFile of this.#affectedFileSet) {
|
|
562
|
-
if (!PathUtils.isChildPath(affectedFile, this.#pkgPath)) {
|
|
563
|
-
continue;
|
|
564
|
-
}
|
|
554
|
+
this._debug(`개별 파일 진단 수집 중...`);
|
|
565
555
|
|
|
566
|
-
|
|
556
|
+
for (const affectedFile of this._affectedFileSet) {
|
|
557
|
+
if (!PathUtils.isChildPath(affectedFile, this._opt.pkgPath)) continue;
|
|
567
558
|
|
|
559
|
+
const affectedSourceFile = this._program!.getSourceFile(affectedFile);
|
|
568
560
|
if (
|
|
569
561
|
!affectedSourceFile ||
|
|
570
|
-
(this
|
|
562
|
+
(this._ngProgram && this._ngProgram.compiler.ignoreForDiagnostics.has(affectedSourceFile))
|
|
571
563
|
) {
|
|
572
564
|
continue;
|
|
573
565
|
}
|
|
574
566
|
|
|
575
567
|
// this.#debug(`get diagnostics of file ${affectedFile}...`);
|
|
576
568
|
|
|
577
|
-
this
|
|
569
|
+
this._perf.run("개별 파일 진단 수집", () => {
|
|
578
570
|
diagnostics.push(
|
|
579
|
-
...this
|
|
580
|
-
...this
|
|
571
|
+
...this._program!.getSyntacticDiagnostics(affectedSourceFile),
|
|
572
|
+
...this._program!.getSemanticDiagnostics(affectedSourceFile),
|
|
581
573
|
);
|
|
582
574
|
});
|
|
583
575
|
|
|
584
|
-
if (this
|
|
585
|
-
this
|
|
586
|
-
if (affectedSourceFile.isDeclarationFile)
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
576
|
+
if (this._ngProgram) {
|
|
577
|
+
this._perf.run("개별 파일 진단 수집(Angular)", () => {
|
|
578
|
+
if (affectedSourceFile.isDeclarationFile) return;
|
|
589
579
|
|
|
590
580
|
diagnostics.push(
|
|
591
|
-
...this
|
|
581
|
+
...this._ngProgram!.compiler.getDiagnosticsForFile(
|
|
592
582
|
affectedSourceFile,
|
|
593
583
|
OptimizeFor.WholeProgram,
|
|
594
584
|
),
|
|
@@ -597,163 +587,50 @@ export class SdTsCompiler {
|
|
|
597
587
|
}
|
|
598
588
|
}
|
|
599
589
|
|
|
600
|
-
this
|
|
601
|
-
this
|
|
590
|
+
this._perf.run("파일 출력 (emit)", () => {
|
|
591
|
+
this._debug(`파일 출력 준비 중...`);
|
|
602
592
|
|
|
603
593
|
let transformers: ts.CustomTransformers = {};
|
|
604
594
|
|
|
605
|
-
if (this
|
|
595
|
+
if (this._ngProgram) {
|
|
606
596
|
transformers = {
|
|
607
597
|
...transformers,
|
|
608
|
-
...this
|
|
598
|
+
...this._ngProgram.compiler.prepareEmit().transformers,
|
|
609
599
|
};
|
|
610
|
-
(transformers.before ??= []).push(replaceBootstrap(() => this
|
|
600
|
+
(transformers.before ??= []).push(replaceBootstrap(() => this._program!.getTypeChecker()));
|
|
611
601
|
(transformers.before ??= []).push(
|
|
612
602
|
createWorkerTransformer((file, importer) => {
|
|
613
603
|
const fullPath = path.resolve(path.dirname(importer), file);
|
|
614
|
-
const relPath = path.relative(path.resolve(this
|
|
604
|
+
const relPath = path.relative(path.resolve(this._opt.pkgPath, "src"), fullPath);
|
|
615
605
|
return relPath.replace(/\.ts$/, "").replaceAll("\\", "/") + ".js";
|
|
616
606
|
}),
|
|
617
607
|
);
|
|
618
608
|
}
|
|
619
|
-
// (transformers.before ??= []).push(transformKeys(this.#program));
|
|
620
|
-
|
|
621
|
-
/*const fixImportTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
|
|
622
|
-
return (sf) => {
|
|
623
|
-
const shouldAppendJs = (importText: string): string | undefined => {
|
|
624
|
-
const resolved = ts.resolveModuleName(
|
|
625
|
-
importText,
|
|
626
|
-
sf.fileName,
|
|
627
|
-
this.#program!.getCompilerOptions(),
|
|
628
|
-
ts.sys,
|
|
629
|
-
);
|
|
630
|
-
|
|
631
|
-
const resolvedInfo = resolved.resolvedModule;
|
|
632
|
-
if (!resolvedInfo) return undefined;
|
|
633
|
-
|
|
634
|
-
const resolvedFileName = resolvedInfo.resolvedFileName;
|
|
635
|
-
|
|
636
|
-
// ① .ts / .tsx / .js / .jsx 만 대상
|
|
637
|
-
if (!/\.(d\.ts|ts|tsx|js|jsx)$/i.test(resolvedFileName)) return undefined;
|
|
638
|
-
|
|
639
|
-
// ② 사용자가 .js, .mjs, .json 등 명시한 경우 무시
|
|
640
|
-
if (/\.[mc]?js$|\.json$/i.test(importText)) return undefined;
|
|
641
|
-
|
|
642
|
-
// 3. import 경로의 마지막 부분이 파일명(확장자 제외)과 같으면 → .js 붙여야 함
|
|
643
|
-
const importLastName = importText.split("/").pop();
|
|
644
|
-
const resolvedFileNameOnly = path.basename(resolvedFileName)
|
|
645
|
-
.replace(/\.(d\.ts|ts|tsx|js|jsx)$/, "");
|
|
646
|
-
|
|
647
|
-
if (importLastName === resolvedFileNameOnly) {
|
|
648
|
-
return importText + ".js";
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// 4. 그렇지 않으면 → index.ts 같은 루트 패키지 import → .js 붙이지 않음
|
|
652
|
-
return undefined;
|
|
653
|
-
};
|
|
654
|
-
|
|
655
|
-
const visitor: ts.Visitor = (node): ts.Node => {
|
|
656
|
-
// import { x } from "./foo"
|
|
657
|
-
if (
|
|
658
|
-
ts.isImportDeclaration(node) &&
|
|
659
|
-
ts.isStringLiteral(node.moduleSpecifier)
|
|
660
|
-
) {
|
|
661
|
-
const newPath = shouldAppendJs(node.moduleSpecifier.text);
|
|
662
|
-
if (newPath != null) {
|
|
663
|
-
return ts.factory.updateImportDeclaration(
|
|
664
|
-
node,
|
|
665
|
-
node.modifiers,
|
|
666
|
-
node.importClause,
|
|
667
|
-
ts.factory.createStringLiteral(newPath),
|
|
668
|
-
undefined,
|
|
669
|
-
);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
609
|
|
|
673
|
-
|
|
674
|
-
if (
|
|
675
|
-
ts.isExportDeclaration(node) &&
|
|
676
|
-
node.moduleSpecifier &&
|
|
677
|
-
ts.isStringLiteral(node.moduleSpecifier)
|
|
678
|
-
) {
|
|
679
|
-
const newPath = shouldAppendJs(node.moduleSpecifier.text);
|
|
680
|
-
if (newPath != null) {
|
|
681
|
-
return ts.factory.updateExportDeclaration(
|
|
682
|
-
node,
|
|
683
|
-
node.modifiers,
|
|
684
|
-
node.isTypeOnly,
|
|
685
|
-
node.exportClause,
|
|
686
|
-
ts.factory.createStringLiteral(newPath),
|
|
687
|
-
undefined,
|
|
688
|
-
);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// dynamic import("./baz")
|
|
693
|
-
if (
|
|
694
|
-
ts.isCallExpression(node) &&
|
|
695
|
-
node.expression.kind === ts.SyntaxKind.ImportKeyword &&
|
|
696
|
-
node.arguments.length === 1 &&
|
|
697
|
-
ts.isStringLiteral(node.arguments[0])
|
|
698
|
-
) {
|
|
699
|
-
const newPath = shouldAppendJs(node.arguments[0].text);
|
|
700
|
-
if (newPath != null) {
|
|
701
|
-
return ts.factory.updateCallExpression(
|
|
702
|
-
node,
|
|
703
|
-
node.expression,
|
|
704
|
-
undefined,
|
|
705
|
-
[ts.factory.createStringLiteral(newPath)],
|
|
706
|
-
);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
return ts.visitEachChild(node, visitor, context);
|
|
711
|
-
};
|
|
712
|
-
|
|
713
|
-
return ts.visitNode(sf, visitor) as ts.SourceFile;
|
|
714
|
-
};
|
|
715
|
-
};
|
|
716
|
-
(transformers.before ??= []).push(fixImportTransformer);*/
|
|
717
|
-
|
|
718
|
-
this.#debug(`emit for files...`);
|
|
610
|
+
this._debug(`파일 출력 중...`);
|
|
719
611
|
|
|
720
612
|
// affected에 새로 추가된 파일은 포함되지 않는 현상이 있어 sourceFileSet으로 바꿈
|
|
721
613
|
// 비교해보니, 딱히 getSourceFiles라서 더 느려지는것 같지는 않음
|
|
722
614
|
// 그래도 affected로 다시 테스트 (조금이라도 더 빠르게)
|
|
723
|
-
for (const affectedFile of this
|
|
724
|
-
if (this
|
|
725
|
-
continue;
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
const sf = this.#program!.getSourceFile(affectedFile);
|
|
729
|
-
if (!sf) {
|
|
730
|
-
continue;
|
|
731
|
-
}
|
|
615
|
+
for (const affectedFile of this._affectedFileSet) {
|
|
616
|
+
if (this._emittedFilesCacheMap.has(affectedFile)) continue;
|
|
732
617
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
618
|
+
const sf = this._program!.getSourceFile(affectedFile);
|
|
619
|
+
if (!sf || sf.isDeclarationFile) continue;
|
|
620
|
+
if (this._ngProgram?.compiler.ignoreForEmit.has(sf)) continue;
|
|
621
|
+
if (this._ngProgram?.compiler.incrementalCompilation.safeToSkipEmit(sf)) continue;
|
|
736
622
|
|
|
737
|
-
|
|
623
|
+
// 번들이 아닌 외부패키지는 보통 emit안해도 됨
|
|
624
|
+
// but esbuild를 통해 bundle로 묶어야 하는놈들은 모든 output이 있어야 함.
|
|
625
|
+
if (!this._opt.isForBundle && !PathUtils.isChildPath(sf.fileName, this._opt.pkgPath)) {
|
|
738
626
|
continue;
|
|
739
627
|
}
|
|
740
628
|
|
|
741
|
-
|
|
742
|
-
continue;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
// esbuild를 통해 bundle로 묶어야 하는놈들은 모든 output이 있어야 함.
|
|
746
|
-
if (!this.#isForBundle) {
|
|
747
|
-
if (!PathUtils.isChildPath(sf.fileName, this.#pkgPath)) {
|
|
748
|
-
continue;
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
this.#program!.emit(
|
|
629
|
+
this._program!.emit(
|
|
753
630
|
sf,
|
|
754
631
|
(fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
|
|
755
632
|
if (!sourceFiles || sourceFiles.length === 0) {
|
|
756
|
-
|
|
633
|
+
tsconf.compilerHost.writeFile(
|
|
757
634
|
fileName,
|
|
758
635
|
text,
|
|
759
636
|
writeByteOrderMark,
|
|
@@ -765,44 +642,22 @@ export class SdTsCompiler {
|
|
|
765
642
|
}
|
|
766
643
|
|
|
767
644
|
const sourceFile = ts.getOriginalNode(sourceFiles[0], ts.isSourceFile);
|
|
768
|
-
if (this
|
|
769
|
-
if (this
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
this.#ngProgram.compiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
645
|
+
if (this._ngProgram) {
|
|
646
|
+
if (this._ngProgram.compiler.ignoreForEmit.has(sourceFile)) return;
|
|
647
|
+
this._ngProgram.compiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
773
648
|
}
|
|
774
649
|
|
|
775
|
-
const emitFileInfoCaches = this
|
|
776
|
-
sourceFile.fileName),
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
PathUtils.isChildPath(
|
|
783
|
-
realFilePath,
|
|
784
|
-
path.resolve(this.#distPath, path.basename(this.#pkgPath), "src"),
|
|
785
|
-
)
|
|
786
|
-
) {
|
|
787
|
-
realFilePath = PathUtils.norm(
|
|
788
|
-
this.#distPath,
|
|
789
|
-
path.relative(
|
|
790
|
-
path.resolve(this.#distPath, path.basename(this.#pkgPath), "src"),
|
|
791
|
-
realFilePath,
|
|
792
|
-
),
|
|
793
|
-
);
|
|
794
|
-
|
|
795
|
-
if (fileName.endsWith(".js.map")) {
|
|
796
|
-
const sourceMapContents = JSON.parse(realText);
|
|
797
|
-
// remove "../../"
|
|
798
|
-
sourceMapContents.sources[0] = sourceMapContents.sources[0].slice(6);
|
|
799
|
-
realText = JSON.stringify(sourceMapContents);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
650
|
+
const emitFileInfoCaches = this._emittedFilesCacheMap.getOrCreate(
|
|
651
|
+
PathUtils.norm(sourceFile.fileName),
|
|
652
|
+
[],
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
if (PathUtils.isChildPath(sourceFile.fileName, this._opt.pkgPath)) {
|
|
656
|
+
const real = this._convertOutputToReal(fileName, tsconf.distPath, text);
|
|
802
657
|
|
|
803
658
|
emitFileInfoCaches.push({
|
|
804
|
-
outAbsPath:
|
|
805
|
-
text:
|
|
659
|
+
outAbsPath: real.filePath,
|
|
660
|
+
text: real.text,
|
|
806
661
|
});
|
|
807
662
|
}
|
|
808
663
|
else {
|
|
@@ -820,32 +675,32 @@ export class SdTsCompiler {
|
|
|
820
675
|
|
|
821
676
|
//-- global style
|
|
822
677
|
if (
|
|
823
|
-
this
|
|
824
|
-
FsUtils.exists(this
|
|
825
|
-
!this
|
|
678
|
+
this._opt.globalStyleFilePath != null &&
|
|
679
|
+
FsUtils.exists(this._opt.globalStyleFilePath) &&
|
|
680
|
+
!this._emittedFilesCacheMap.has(this._opt.globalStyleFilePath)
|
|
826
681
|
) {
|
|
827
|
-
this
|
|
682
|
+
this._debug(`전역 스타일 번들링 중...`);
|
|
828
683
|
|
|
829
|
-
await this
|
|
830
|
-
const data = FsUtils.readFile(this
|
|
831
|
-
const
|
|
684
|
+
await this._perf.run("전역 스타일 번들링", async () => {
|
|
685
|
+
const data = FsUtils.readFile(this._opt.globalStyleFilePath!);
|
|
686
|
+
const stylesheetBundlingResult = await this._bundleStylesheetAsync(
|
|
832
687
|
data,
|
|
833
|
-
this
|
|
834
|
-
this
|
|
688
|
+
this._opt.globalStyleFilePath!,
|
|
689
|
+
this._opt.globalStyleFilePath,
|
|
835
690
|
);
|
|
836
|
-
const emitFileInfos = this
|
|
837
|
-
this
|
|
691
|
+
const emitFileInfos = this._emittedFilesCacheMap.getOrCreate(
|
|
692
|
+
this._opt.globalStyleFilePath!,
|
|
838
693
|
[],
|
|
839
694
|
);
|
|
840
695
|
emitFileInfos.push({
|
|
841
696
|
outAbsPath: PathUtils.norm(
|
|
842
|
-
this
|
|
843
|
-
path.relative(path.resolve(this
|
|
697
|
+
this._opt.pkgPath,
|
|
698
|
+
path.relative(path.resolve(this._opt.pkgPath, "src"), this._opt.globalStyleFilePath!)
|
|
844
699
|
.replace(/\.scss$/, ".css"),
|
|
845
700
|
),
|
|
846
|
-
text: contents,
|
|
701
|
+
text: stylesheetBundlingResult.contents ?? "",
|
|
847
702
|
});
|
|
848
|
-
emitFileSet.add(this
|
|
703
|
+
emitFileSet.add(this._opt.globalStyleFilePath!);
|
|
849
704
|
});
|
|
850
705
|
}
|
|
851
706
|
|
|
@@ -855,215 +710,35 @@ export class SdTsCompiler {
|
|
|
855
710
|
};
|
|
856
711
|
}
|
|
857
712
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
#findDeps(sf: ts.SourceFile) {
|
|
863
|
-
const deps: ({
|
|
864
|
-
fileName: TNormPath;
|
|
865
|
-
importName: string;
|
|
866
|
-
exportName?: string;
|
|
867
|
-
} | ISdBuildMessage)[] = [];
|
|
868
|
-
|
|
869
|
-
const tc = this.#program!.getTypeChecker();
|
|
870
|
-
|
|
871
|
-
const visit = (node: ts.Node) => {
|
|
872
|
-
if (ts.isExportDeclaration(node)) {
|
|
873
|
-
if (node.moduleSpecifier) {
|
|
874
|
-
const moduleSymbol = tc.getSymbolAtLocation(node.moduleSpecifier);
|
|
875
|
-
if (!moduleSymbol) {
|
|
876
|
-
const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
877
|
-
deps.push({
|
|
878
|
-
filePath: PathUtils.norm(sf.fileName),
|
|
879
|
-
line: pos.line,
|
|
880
|
-
char: pos.character,
|
|
881
|
-
code: undefined,
|
|
882
|
-
severity: "error",
|
|
883
|
-
message: "export moduleSymbol not found",
|
|
884
|
-
type: "deps",
|
|
885
|
-
});
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
const decls = moduleSymbol.getDeclarations();
|
|
890
|
-
if (!decls) {
|
|
891
|
-
const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
892
|
-
deps.push({
|
|
893
|
-
filePath: PathUtils.norm(sf.fileName),
|
|
894
|
-
line: pos.line,
|
|
895
|
-
char: pos.character,
|
|
896
|
-
code: undefined,
|
|
897
|
-
severity: "error",
|
|
898
|
-
message: "export decls not found",
|
|
899
|
-
type: "deps",
|
|
900
|
-
});
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
const namedBindings = node.exportClause;
|
|
905
|
-
if (namedBindings && ts.isNamedExports(namedBindings)) {
|
|
906
|
-
for (const el of namedBindings.elements) {
|
|
907
|
-
for (const decl of decls) {
|
|
908
|
-
deps.push({
|
|
909
|
-
fileName: PathUtils.norm(decl.getSourceFile().fileName),
|
|
910
|
-
importName: el.name.text,
|
|
911
|
-
exportName: el.propertyName?.text ?? el.name.text,
|
|
912
|
-
});
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
else {
|
|
917
|
-
if (!moduleSymbol.exports) {
|
|
918
|
-
const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
919
|
-
deps.push({
|
|
920
|
-
filePath: PathUtils.norm(sf.fileName),
|
|
921
|
-
line: pos.line,
|
|
922
|
-
char: pos.character,
|
|
923
|
-
code: undefined,
|
|
924
|
-
severity: "error",
|
|
925
|
-
message: "moduleSymbol exports not found",
|
|
926
|
-
type: "deps",
|
|
927
|
-
});
|
|
928
|
-
return;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
for (const decl of decls) {
|
|
932
|
-
for (const key of moduleSymbol.exports.keys()) {
|
|
933
|
-
deps.push({
|
|
934
|
-
fileName: PathUtils.norm(decl.getSourceFile().fileName),
|
|
935
|
-
importName: key.toString(),
|
|
936
|
-
exportName: key.toString(),
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
else if (ts.isImportDeclaration(node)) {
|
|
944
|
-
const moduleSymbol = tc.getSymbolAtLocation(node.moduleSpecifier);
|
|
945
|
-
if (!moduleSymbol) {
|
|
946
|
-
if (ts.isStringLiteral(node.moduleSpecifier)
|
|
947
|
-
&& node.moduleSpecifier.text.startsWith("./")) {
|
|
948
|
-
deps.push({
|
|
949
|
-
fileName: PathUtils.norm(path.resolve(
|
|
950
|
-
path.dirname(sf.fileName),
|
|
951
|
-
node.moduleSpecifier.text + ".ts",
|
|
952
|
-
)),
|
|
953
|
-
importName: "*",
|
|
954
|
-
});
|
|
955
|
-
|
|
956
|
-
// const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
957
|
-
// deps.push({
|
|
958
|
-
// filePath: PathUtil.norm(sf.fileName),
|
|
959
|
-
// line: pos.line,
|
|
960
|
-
// char: pos.character,
|
|
961
|
-
// code: undefined,
|
|
962
|
-
// severity: "error",
|
|
963
|
-
// message: `import moduleSymbol not found (${node.moduleSpecifier.text})`,
|
|
964
|
-
// type: "deps",
|
|
965
|
-
// });
|
|
966
|
-
// return;
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
/*else {
|
|
970
|
-
throw new NeverEntryError(`import moduleSymbol: ${sf.fileName} ${node.moduleSpecifier["text"]}`);
|
|
971
|
-
}*/
|
|
972
|
-
}
|
|
973
|
-
else {
|
|
974
|
-
const decls = moduleSymbol.getDeclarations();
|
|
975
|
-
if (!decls) {
|
|
976
|
-
const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
977
|
-
deps.push({
|
|
978
|
-
filePath: PathUtils.norm(sf.fileName),
|
|
979
|
-
line: pos.line,
|
|
980
|
-
char: pos.character,
|
|
981
|
-
code: undefined,
|
|
982
|
-
severity: "error",
|
|
983
|
-
message: `import decls not found (${moduleSymbol.name})`,
|
|
984
|
-
type: "deps",
|
|
985
|
-
});
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
713
|
+
private _convertOutputToReal(filePath: string, distPath: string, text: string) {
|
|
714
|
+
let realFilePath = PathUtils.norm(filePath);
|
|
715
|
+
let realText = text;
|
|
988
716
|
|
|
989
|
-
|
|
990
|
-
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
991
|
-
for (const el of namedBindings.elements) {
|
|
992
|
-
for (const decl of decls) {
|
|
993
|
-
deps.push({
|
|
994
|
-
fileName: PathUtils.norm(decl.getSourceFile().fileName),
|
|
995
|
-
importName: el.name.text,
|
|
996
|
-
});
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
else {
|
|
1001
|
-
for (const decl of decls) {
|
|
1002
|
-
deps.push({
|
|
1003
|
-
fileName: PathUtils.norm(decl.getSourceFile().fileName),
|
|
1004
|
-
importName: "*",
|
|
1005
|
-
});
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
717
|
+
const srcRelBasePath = path.resolve(distPath, path.basename(this._opt.pkgPath), "src");
|
|
1010
718
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
const moduleSymbol = tc.getSymbolAtLocation(node.arguments[0]);
|
|
1015
|
-
if (!moduleSymbol) {
|
|
1016
|
-
deps.push({
|
|
1017
|
-
fileName: PathUtils.norm(path.resolve(
|
|
1018
|
-
path.dirname(sf.fileName),
|
|
1019
|
-
node.arguments[0].text + ".ts",
|
|
1020
|
-
)),
|
|
1021
|
-
importName: "*",
|
|
1022
|
-
});
|
|
1023
|
-
|
|
1024
|
-
// const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
1025
|
-
// deps.push({
|
|
1026
|
-
// filePath: PathUtil.norm(sf.fileName),
|
|
1027
|
-
// line: pos.line,
|
|
1028
|
-
// char: pos.character,
|
|
1029
|
-
// code: undefined,
|
|
1030
|
-
// severity: "error",
|
|
1031
|
-
// message: `import() moduleSymbol not found (${node.arguments[0].text})`,
|
|
1032
|
-
// type: "deps",
|
|
1033
|
-
// });
|
|
1034
|
-
// return;
|
|
1035
|
-
}
|
|
1036
|
-
else {
|
|
1037
|
-
const decls = moduleSymbol.getDeclarations();
|
|
1038
|
-
if (!decls) {
|
|
1039
|
-
const pos = ts.getLineAndCharacterOfPosition(sf, node.getStart());
|
|
1040
|
-
deps.push({
|
|
1041
|
-
filePath: PathUtils.norm(sf.fileName),
|
|
1042
|
-
line: pos.line,
|
|
1043
|
-
char: pos.character,
|
|
1044
|
-
code: undefined,
|
|
1045
|
-
severity: "error",
|
|
1046
|
-
message: `import() decls not found (${node.arguments[0].text})`,
|
|
1047
|
-
type: "deps",
|
|
1048
|
-
});
|
|
1049
|
-
return;
|
|
1050
|
-
}
|
|
719
|
+
if (PathUtils.isChildPath(realFilePath, srcRelBasePath)) {
|
|
720
|
+
realFilePath = PathUtils.norm(distPath, path.relative(srcRelBasePath, realFilePath));
|
|
1051
721
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
722
|
+
// source map 위치 정확히 찾아가기
|
|
723
|
+
if (filePath.endsWith(".js.map")) {
|
|
724
|
+
const sourceMapContents = JSON.parse(realText);
|
|
725
|
+
sourceMapContents.sources[0] = sourceMapContents.sources[0].slice(6); // remove "../../"
|
|
726
|
+
realText = JSON.stringify(sourceMapContents);
|
|
1060
727
|
}
|
|
728
|
+
}
|
|
1061
729
|
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
sf.forEachChild(visit);
|
|
730
|
+
return { filePath: realFilePath, text: realText };
|
|
731
|
+
}
|
|
1066
732
|
|
|
1067
|
-
|
|
733
|
+
private _debug(...msg: any[]): void {
|
|
734
|
+
this._logger.debug(`[${path.basename(this._opt.pkgPath)}]`, ...msg);
|
|
1068
735
|
}
|
|
1069
736
|
}
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
interface ITsConfigInfo {
|
|
740
|
+
fileNames: string[];
|
|
741
|
+
options: ts.CompilerOptions;
|
|
742
|
+
compilerHost: ts.CompilerHost;
|
|
743
|
+
distPath: string;
|
|
744
|
+
}
|