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