@simplysm/sd-cli 11.0.3 → 11.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/build-cluster.js +1 -1
  2. package/dist/build-cluster.js.map +1 -1
  3. package/dist/build-tools/SdLinter.js +2 -2
  4. package/dist/build-tools/SdLinter.js.map +1 -1
  5. package/dist/build-tools/SdNgBundler.d.ts +23 -0
  6. package/dist/build-tools/SdNgBundler.js +331 -0
  7. package/dist/build-tools/SdNgBundler.js.map +1 -0
  8. package/dist/build-tools/SdTsBundler.d.ts +15 -0
  9. package/dist/build-tools/SdTsBundler.js +96 -0
  10. package/dist/build-tools/SdTsBundler.js.map +1 -0
  11. package/dist/build-tools/SdTsCompiler.d.ts +28 -0
  12. package/dist/build-tools/SdTsCompiler.js +212 -0
  13. package/dist/build-tools/SdTsCompiler.js.map +1 -0
  14. package/dist/builders/SdCliClientBuilder.d.ts +4 -2
  15. package/dist/builders/SdCliClientBuilder.js +60 -297
  16. package/dist/builders/SdCliClientBuilder.js.map +1 -1
  17. package/dist/builders/SdCliServerBuilder.js +79 -216
  18. package/dist/builders/SdCliServerBuilder.js.map +1 -1
  19. package/dist/builders/SdCliTsLibBuilder.d.ts +0 -1
  20. package/dist/builders/SdCliTsLibBuilder.js +35 -33
  21. package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
  22. package/dist/commons.d.ts +7 -0
  23. package/dist/entry/SdCliProject.js +13 -10
  24. package/dist/entry/SdCliProject.js.map +1 -1
  25. package/dist/index.d.ts +3 -1
  26. package/dist/index.js +3 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/server-worker.js +3 -0
  29. package/dist/server-worker.js.map +1 -1
  30. package/dist/utils/SdCliBuildResultUtil.d.ts +1 -1
  31. package/dist/utils/SdCliBuildResultUtil.js +4 -4
  32. package/dist/utils/SdCliBuildResultUtil.js.map +1 -1
  33. package/package.json +14 -12
  34. package/src/build-cluster.ts +1 -1
  35. package/src/build-tools/SdLinter.ts +2 -2
  36. package/src/build-tools/SdNgBundler.ts +404 -0
  37. package/src/build-tools/SdTsBundler.ts +106 -0
  38. package/src/build-tools/SdTsCompiler.ts +304 -0
  39. package/src/builders/SdCliClientBuilder.ts +75 -322
  40. package/src/builders/SdCliServerBuilder.ts +95 -243
  41. package/src/builders/SdCliTsLibBuilder.ts +39 -40
  42. package/src/commons.ts +6 -0
  43. package/src/entry/SdCliProject.ts +17 -12
  44. package/src/index.ts +3 -1
  45. package/src/server-worker.ts +3 -0
  46. package/src/utils/SdCliBuildResultUtil.ts +4 -4
  47. package/dist/build-tools/SdTsIncrementalBuilder.d.ts +0 -31
  48. package/dist/build-tools/SdTsIncrementalBuilder.js +0 -126
  49. package/dist/build-tools/SdTsIncrementalBuilder.js.map +0 -1
  50. package/src/build-tools/SdTsIncrementalBuilder.ts +0 -207
@@ -1,29 +1,17 @@
1
1
  import {EventEmitter} from "events";
2
2
  import {FsUtil, Logger, PathUtil, SdFsWatcher} from "@simplysm/sd-core-node";
3
3
  import {ISdCliBuilderResult, ISdCliClientPackageConfig, ISdCliConfig, ISdCliPackageBuildResult} from "../commons";
4
- import {FunctionQueue, NotImplementError} from "@simplysm/sd-core-common";
4
+ import {FunctionQueue, Wait} from "@simplysm/sd-core-common";
5
5
  import path from "path";
6
- import esbuild from "esbuild";
7
- import {createVirtualModulePlugin} from "@angular-devkit/build-angular/src/tools/esbuild/virtual-module-plugin";
8
- import {
9
- createSourcemapIgnorelistPlugin
10
- } from "@angular-devkit/build-angular/src/tools/esbuild/sourcemap-ignorelist-plugin";
11
- import {
12
- createCompilerPlugin,
13
- SourceFileCache
14
- } from "@angular-devkit/build-angular/src/tools/esbuild/angular/compiler-plugin";
15
- import {createCompilerPluginOptions} from "@angular-devkit/build-angular/src/tools/esbuild/compiler-plugin-options";
16
- import {CrossOrigin} from "@angular-devkit/build-angular/src/builders/application/schema";
17
-
18
- import nodeStdLibBrowserPlugin from "node-stdlib-browser/helpers/esbuild/plugin";
19
- import nodeStdLibBrowser from "node-stdlib-browser";
20
- import {fileURLToPath} from "url";
21
- import {SdTsIncrementalBuilder} from "../build-tools/SdTsIncrementalBuilder";
6
+ import {SdTsCompiler} from "../build-tools/SdTsCompiler";
7
+ import {SdNgBundler} from "../build-tools/SdNgBundler";
22
8
  import {SdLinter} from "../build-tools/SdLinter";
23
9
 
24
10
  export class SdCliClientBuilder extends EventEmitter {
25
11
  private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdCliClientBuilder"]);
26
12
  private readonly _pkgConf: ISdCliClientPackageConfig;
13
+ private _builders?: SdNgBundler[];
14
+ private _checker?: SdTsCompiler;
27
15
 
28
16
  public constructor(private readonly _projConf: ISdCliConfig,
29
17
  private readonly _pkgPath: string) {
@@ -38,337 +26,102 @@ export class SdCliClientBuilder extends EventEmitter {
38
26
  return this;
39
27
  }
40
28
 
41
- public async watchAsync(): Promise<void> {
42
- this._debug("빌드 준비...");
43
- const sdTsProgram = await SdTsIncrementalBuilder.createAsync(this._pkgPath, () => ({emitJs: false}));
44
-
29
+ public async buildAsync(): Promise<ISdCliBuilderResult> {
45
30
  this._debug("dist 초기화...");
46
31
  await FsUtil.removeAsync(path.resolve(this._pkgPath, "dist"));
47
32
 
48
- this.emit("change");
49
-
50
- if (this._pkgConf.server !== undefined) {
51
- this._debug("GEN .config...");
52
- const confDistPath = path.resolve(this._pkgPath, "../../packages", this._pkgConf.server, "dist/www", path.basename(this._pkgPath), ".config.json");
53
- await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
54
- }
55
-
56
- this._debug("BUILD...");
57
- const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as ("web")[]);
58
- const cache = new SourceFileCache();
59
- const options = await Promise.all(builderTypes.map((builderType) => this._getEsBuildOptionsAsync({
60
- dev: true,
61
- builderType,
62
- cache
63
- })));
64
- const contexts = await Promise.all(options.map((esbuildOption) => esbuild.context(esbuildOption)));
65
- const results = await Promise.all(contexts.map(async (ctx) => {
66
- try {
67
- return await ctx.rebuild();
68
- }
69
- catch (err) {
70
- if (typeof err === "object" && "errors" in err && "warnings" in err) {
71
- return {
72
- errors: err.errors,
73
- warnings: err.warnings
74
- };
75
- }
76
- throw new err;
77
- }
78
- }));
79
-
80
- const buildResults: ISdCliPackageBuildResult[] = results.mapMany((esbuildResult) => [
81
- ...esbuildResult.warnings.map((warn) => ({
82
- filePath: warn.location?.file !== undefined ? path.resolve(warn.location.file) : undefined,
83
- line: warn.location?.line,
84
- char: warn.location?.column,
85
- code: undefined,
86
- severity: "warning" as const,
87
- message: warn.text,
88
- type: "build" as const
89
- })),
90
- ...esbuildResult.errors.map((err) => ({
91
- filePath: err.location?.file !== undefined ? path.resolve(err.location.file) : undefined,
92
- line: err.location?.line,
93
- char: err.location?.column !== undefined ? err.location.column + 1 : undefined,
94
- code: undefined,
95
- severity: "warning" as const,
96
- message: err.text,
97
- type: "build" as const
98
- }))
99
- ]);
33
+ return await this._runAsync({dev: false, genConf: true});
34
+ }
100
35
 
101
- this._debug("CHECK...");
102
- const checkResult = await sdTsProgram.buildAsync();
36
+ public async watchAsync(): Promise<void> {
37
+ this.emit("change");
103
38
 
104
- this._debug("LINT...");
105
- const lintResults = await SdLinter.lintAsync(checkResult.affectedFilePaths, sdTsProgram.builderProgram!.getProgram());
39
+ this._debug("dist 초기화...");
40
+ await FsUtil.removeAsync(path.resolve(this._pkgPath, "dist"));
106
41
 
107
- this._debug(`빌드 완료`);
108
- this.emit("complete", {
109
- affectedFilePaths: checkResult.affectedFilePaths,
110
- buildResults: [...buildResults, ...checkResult.results, ...lintResults]
111
- });
42
+ const result = await this._runAsync({dev: true, genConf: true});
43
+ this.emit("complete", result);
112
44
 
113
45
  this._debug("WATCH...");
114
46
  const fnQ = new FunctionQueue();
115
- SdFsWatcher
47
+ const watcher = SdFsWatcher
116
48
  .watch([
117
- ...sdTsProgram.builderProgram!.getSourceFiles().map((item) => item.fileName),
118
- path.resolve(this._pkgPath, "src/**/*.{ts,tsx}")
49
+ ...result.watchFilePaths,
50
+ path.resolve(this._pkgPath, "src/**/*.*")
119
51
  ])
120
- .onChange({
121
- delay: 100
122
- }, (changeInfos) => {
123
- for (const changeInfo of changeInfos) {
124
- cache.delete(PathUtil.posix(changeInfo.path));
52
+ .onChange({delay: 100}, (changeInfos) => {
53
+ for (const builder of this._builders!) {
54
+ builder.removeCache(changeInfos.map((item) => item.path));
125
55
  }
126
56
 
127
57
  fnQ.runLast(async () => {
128
58
  this.emit("change");
129
59
 
130
- this._debug(`BUILD...`);
131
- const watchResults = await Promise.all(contexts.map(async (ctx) => {
132
- try {
133
- return await ctx.rebuild();
134
- }
135
- catch (err) {
136
- if (typeof err === "object" && "errors" in err && "warnings" in err) {
137
- return {
138
- errors: err.errors,
139
- warnings: err.warnings
140
- };
141
- }
142
- throw new err;
143
- }
144
- }));
145
-
146
- const watchBuildResults: ISdCliPackageBuildResult[] = watchResults.mapMany((esbuildResult) => [
147
- ...esbuildResult.warnings.map((warn) => ({
148
- filePath: warn.location?.file !== undefined ? path.resolve(warn.location.file) : undefined,
149
- line: warn.location?.line,
150
- char: warn.location?.column,
151
- code: undefined,
152
- severity: "warning" as const,
153
- message: warn.text,
154
- type: "build" as const
155
- })),
156
- ...esbuildResult.errors.map((err) => ({
157
- filePath: err.location?.file !== undefined ? path.resolve(err.location.file) : undefined,
158
- line: err.location?.line,
159
- char: err.location?.column !== undefined ? err.location.column + 1 : undefined,
160
- code: undefined,
161
- severity: "warning" as const,
162
- message: err.text,
163
- type: "build" as const
164
- }))
165
- ]);
60
+ const watchResult = await this._runAsync({dev: true, genConf: false});
61
+ this.emit("complete", watchResult);
166
62
 
167
- this._debug("CHECK...");
168
- const watchCheckResult = await sdTsProgram.buildAsync();
169
-
170
- this._debug(`LINT...`);
171
- const watchLintResults = await SdLinter.lintAsync(watchCheckResult.affectedFilePaths, sdTsProgram.builderProgram!.getProgram());
172
-
173
- this._debug(`빌드 완료`);
174
- this.emit("complete", {
175
- affectedFilePaths: watchCheckResult.affectedFilePaths,
176
- buildResults: [...watchBuildResults, ...watchCheckResult.results, ...watchLintResults]
177
- });
63
+ watcher.add(watchResult.watchFilePaths);
178
64
  });
179
65
  });
180
66
  }
181
67
 
182
- // eslint-disable-next-line @typescript-eslint/require-await
183
- public async buildAsync(): Promise<ISdCliBuilderResult> {
184
- throw new NotImplementError();
185
- }
186
-
187
- private async _getEsBuildOptionsAsync(opt: {
68
+ private async _runAsync(opt: {
188
69
  dev: boolean;
189
- builderType: "web",
190
- cache: SourceFileCache
191
- }): Promise<esbuild.BuildOptions> {
192
- // const projPath = path.resolve(this._pkgPath, "../../");
193
- const tsconfigFilePath = path.resolve(this._pkgPath, "tsconfig.json");
194
- const mainFilePath = path.resolve(this._pkgPath, "src/main.ts");
195
- const indexHtmlFilePath = path.resolve(this._pkgPath, "src/index.html");
70
+ genConf: boolean;
71
+ }): Promise<{
72
+ watchFilePaths: string[];
73
+ affectedFilePaths: string[];
74
+ buildResults: ISdCliPackageBuildResult[];
75
+ }> {
76
+ this._debug(`BUILD 준비...`);
77
+ const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as ("web")[]);
78
+ this._builders = this._builders ?? builderTypes.map((builderType) => new SdNgBundler({
79
+ dev: opt.dev,
80
+ builderType: builderType,
81
+ pkgPath: this._pkgPath
82
+ }));
83
+
84
+ this._checker = this._checker ?? new SdTsCompiler({
85
+ pkgPath: this._pkgPath,
86
+ emit: false,
87
+ emitDts: false,
88
+ globalStyle: false
89
+ });
90
+
91
+ this._debug(`BUILD...`);
92
+ const buildResults = await Promise.all(this._builders.map((builder) => builder.bundleAsync()));
196
93
 
197
- const cacheBasePath = path.resolve(this._pkgPath, ".cache");
198
- const distBasePath = path.resolve(this._pkgPath, "dist");
94
+ this._debug("CHECK...");
95
+ const checkResult = await this._checker.buildAsync();
199
96
 
200
- const {pluginOptions, styleOptions} = createCompilerPluginOptions(
201
- {
202
- advancedOptimizations: true,
203
- allowedCommonJsDependencies: [],
204
- baseHref: undefined,
205
- cacheOptions: {
206
- enabled: true,
207
- basePath: cacheBasePath,
208
- path: path.resolve(cacheBasePath, opt.builderType)
209
- },
210
- crossOrigin: CrossOrigin.None,
211
- deleteOutputPath: true,
212
- externalDependencies: [],
213
- extractLicenses: false,
214
- inlineStyleLanguage: 'scss',
215
- jit: false,
216
- stats: false,
217
- polyfills: ["./src/polyfills.ts"],
218
- poll: undefined,
219
- progress: true,
220
- externalPackages: true,
221
- preserveSymlinks: true,
222
- stylePreprocessorOptions: {includePaths: []},
223
- subresourceIntegrity: false,
224
- serverEntryPoint: undefined,
225
- prerenderOptions: undefined,
226
- appShellOptions: undefined,
227
- ssrOptions: undefined,
228
- verbose: false,
229
- watch: true,
230
- workspaceRoot: this._pkgPath,
231
- entryPoints: {main: mainFilePath},
232
- optimizationOptions: {
233
- scripts: false,
234
- styles: {minify: false, inlineCritical: false},
235
- fonts: {inline: false}
236
- },
237
- outputPath: distBasePath,
238
- outExtension: undefined,
239
- sourcemapOptions: {vendor: false, hidden: false, scripts: true, styles: true},
240
- tsconfig: tsconfigFilePath,
241
- projectRoot: this._pkgPath,
242
- assets: [
243
- {glob: 'favicon.ico', input: 'src', output: ''},
244
- {glob: '**/*', input: 'src\\assets', output: 'assets'}
245
- ],
246
- outputNames: {bundles: '[name]', media: 'media/[name]'},
247
- fileReplacements: undefined,
248
- globalStyles: [{name: 'styles', files: ["src/styles.scss"], initial: true}],
249
- globalScripts: [],
250
- serviceWorker: undefined,
251
- indexHtmlOptions: {
252
- input: indexHtmlFilePath,
253
- output: 'index.html',
254
- insertionOrder: [
255
- ['runtime', true],
256
- ['polyfills', true],
257
- ['styles', false],
258
- ['vendor', true],
259
- ['main', true]
260
- ]
261
- },
262
- tailwindConfiguration: undefined
263
- },
264
- [
265
- 'chrome117.0', 'chrome116.0',
266
- 'edge117.0', 'edge116.0',
267
- 'firefox118.0', 'firefox115.0',
268
- 'ios17.0', 'ios16.6',
269
- 'ios16.5', 'ios16.4',
270
- 'ios16.3', 'ios16.2',
271
- 'ios16.1', 'ios16.0',
272
- 'safari17.0', 'safari16.6',
273
- 'safari16.5', 'safari16.4',
274
- 'safari16.3', 'safari16.2',
275
- 'safari16.1', 'safari16.0'
276
- ],
277
- opt.cache,
278
- );
97
+ this._debug(`LINT...`);
98
+ const lintResults = await SdLinter.lintAsync(checkResult.affectedFilePaths, this._checker.program);
279
99
 
100
+ if (opt.genConf) {
101
+ this._debug("GEN .config...");
102
+ if (opt.dev && this._pkgConf.server !== undefined) {
103
+ const serverDistPath = path.resolve(this._pkgPath, "../", this._pkgConf.server, "dist");
104
+ await Wait.until(() => FsUtil.exists(serverDistPath));
105
+ await FsUtil.writeJsonAsync(path.resolve(serverDistPath, "www", path.basename(this._pkgPath), ".config.json"), this._pkgConf.configs ?? {}, {space: 2});
106
+ }
107
+ else {
108
+ await FsUtil.writeJsonAsync(path.resolve(this._pkgPath, "dist/.config.json"), this._pkgConf.configs ?? {}, {space: 2});
109
+ }
110
+ }
111
+
112
+ const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
113
+ .mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
114
+ const watchFilePaths = buildResults.mapMany((item) => item.filePaths)
115
+ .filter((item) =>
116
+ PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
117
+ localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
118
+ );
119
+
120
+ this._debug(`빌드 완료`);
280
121
  return {
281
- absWorkingDir: this._pkgPath,
282
- bundle: true,
283
- format: 'esm',
284
- assetNames: 'media/[name]',
285
- conditions: ['es2020', 'es2015', 'module'],
286
- resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
287
- metafile: true,
288
- legalComments: 'eof',
289
- logLevel: 'silent',
290
- minifyIdentifiers: false,
291
- minifySyntax: false,
292
- minifyWhitespace: false,
293
- pure: ['forwardRef'],
294
- outdir: distBasePath,
295
- outExtension: undefined,
296
- sourcemap: true,
297
- splitting: true,
298
- chunkNames: 'chunk-[hash]',
299
- tsconfig: tsconfigFilePath,
300
- external: [],
301
- write: true,
302
- preserveSymlinks: true,
303
- define: {
304
- ngJitMode: 'false',
305
- global: 'global',
306
- process: 'process',
307
- Buffer: 'Buffer'
308
- },
309
- platform: 'browser',
310
- mainFields: ['es2020', 'es2015', 'browser', 'module', 'main'],
311
- entryNames: '[name]',
312
- entryPoints: {
313
- main: mainFilePath,
314
- polyfills: 'angular:polyfills'
315
- },
316
- target: [
317
- 'chrome117.0', 'chrome116.0',
318
- 'edge117.0', 'edge116.0',
319
- 'firefox118.0', 'firefox115.0',
320
- 'ios17.0', 'ios16.6',
321
- 'ios16.5', 'ios16.4',
322
- 'ios16.3', 'ios16.2',
323
- 'ios16.1', 'ios16.0',
324
- 'safari17.0', 'safari16.6',
325
- 'safari16.5', 'safari16.4',
326
- 'safari16.3', 'safari16.2',
327
- 'safari16.1', 'safari16.0'
328
- ],
329
- supported: {'async-await': false, 'object-rest-spread': false},
330
- loader: {
331
- ".png": "file",
332
- ".jpeg": "file",
333
- ".jpg": "file",
334
- ".jfif": "file",
335
- ".gif": "file",
336
- ".svg": "file",
337
- ".woff": "file",
338
- ".woff2": "file",
339
- ".ttf": "file",
340
- ".eot": "file",
341
- ".ico": "file",
342
- ".otf": "file",
343
- ".csv": "file",
344
- ".xlsx": "file",
345
- ".xls": "file",
346
- ".pptx": "file",
347
- ".ppt": "file",
348
- ".docx": "file",
349
- ".doc": "file",
350
- ".zip": "file",
351
- ".pfx": "file",
352
- ".pkl": "file"
353
- },
354
- inject: [PathUtil.posix(fileURLToPath(await import.meta.resolve!("node-stdlib-browser/helpers/esbuild/shim")))],
355
- plugins: [
356
- createVirtualModulePlugin({
357
- namespace: "angular:polyfills",
358
- loadContent: () => ({
359
- contents: `import "./src/polyfills.ts";`,
360
- loader: 'js',
361
- resolveDir: this._pkgPath
362
- })
363
- }) as esbuild.Plugin,
364
- createSourcemapIgnorelistPlugin() as esbuild.Plugin,
365
- createCompilerPlugin(
366
- pluginOptions,
367
- styleOptions
368
- ) as esbuild.Plugin,
369
- // createExternalPackagesPlugin() as esbuild.Plugin,
370
- nodeStdLibBrowserPlugin(nodeStdLibBrowser)
371
- ]
122
+ watchFilePaths: watchFilePaths,
123
+ affectedFilePaths: checkResult.affectedFilePaths,
124
+ buildResults: [...buildResults.mapMany((item) => item.results), ...checkResult.results, ...lintResults]
372
125
  };
373
126
  }
374
127