@simplysm/sd-cli 11.0.9 → 11.0.12

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 (61) hide show
  1. package/dist/build-cluster.js +25 -36
  2. package/dist/build-cluster.js.map +1 -1
  3. package/dist/build-tools/SdCliCordova.js +5 -5
  4. package/dist/build-tools/SdCliCordova.js.map +1 -1
  5. package/dist/build-tools/SdCliNgRoutesFileGenerator.d.ts +4 -0
  6. package/dist/build-tools/SdCliNgRoutesFileGenerator.js +64 -0
  7. package/dist/build-tools/SdCliNgRoutesFileGenerator.js.map +1 -0
  8. package/dist/build-tools/SdLinter.js +8 -1
  9. package/dist/build-tools/SdLinter.js.map +1 -1
  10. package/dist/build-tools/SdNgBundler.d.ts +18 -8
  11. package/dist/build-tools/SdNgBundler.js +286 -213
  12. package/dist/build-tools/SdNgBundler.js.map +1 -1
  13. package/dist/build-tools/SdTsBundler.d.ts +6 -5
  14. package/dist/build-tools/SdTsBundler.js +78 -80
  15. package/dist/build-tools/SdTsBundler.js.map +1 -1
  16. package/dist/build-tools/SdTsCompiler.d.ts +1 -0
  17. package/dist/build-tools/SdTsCompiler.js +5 -1
  18. package/dist/build-tools/SdTsCompiler.js.map +1 -1
  19. package/dist/builders/SdCliClientBuilder.js +51 -36
  20. package/dist/builders/SdCliClientBuilder.js.map +1 -1
  21. package/dist/builders/SdCliServerBuilder.d.ts +6 -2
  22. package/dist/builders/SdCliServerBuilder.js +107 -141
  23. package/dist/builders/SdCliServerBuilder.js.map +1 -1
  24. package/dist/builders/SdCliTsLibBuilder.d.ts +6 -3
  25. package/dist/builders/SdCliTsLibBuilder.js +42 -45
  26. package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
  27. package/dist/commons.d.ts +0 -2
  28. package/dist/entry/SdCliElectron.js +3 -3
  29. package/dist/entry/SdCliElectron.js.map +1 -1
  30. package/dist/entry/SdCliProject.d.ts +0 -3
  31. package/dist/entry/SdCliProject.js +10 -33
  32. package/dist/entry/SdCliProject.js.map +1 -1
  33. package/dist/index.d.ts +3 -0
  34. package/dist/index.js +3 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/sd-cli.js +3 -21
  37. package/dist/sd-cli.js.map +1 -1
  38. package/dist/utils/SdMemoryLoadResultCache.d.ts +9 -0
  39. package/dist/utils/SdMemoryLoadResultCache.js +39 -0
  40. package/dist/utils/SdMemoryLoadResultCache.js.map +1 -0
  41. package/dist/utils/SdSourceFileCache.d.ts +5 -0
  42. package/dist/utils/SdSourceFileCache.js +9 -0
  43. package/dist/utils/SdSourceFileCache.js.map +1 -0
  44. package/package.json +17 -17
  45. package/src/build-cluster.ts +26 -36
  46. package/src/build-tools/SdCliCordova.ts +5 -5
  47. package/src/build-tools/SdCliNgRoutesFileGenerator.ts +80 -0
  48. package/src/build-tools/SdLinter.ts +12 -1
  49. package/src/build-tools/SdNgBundler.ts +431 -333
  50. package/src/build-tools/SdTsBundler.ts +86 -86
  51. package/src/build-tools/SdTsCompiler.ts +6 -1
  52. package/src/builders/SdCliClientBuilder.ts +62 -43
  53. package/src/builders/SdCliServerBuilder.ts +64 -63
  54. package/src/builders/SdCliTsLibBuilder.ts +58 -50
  55. package/src/commons.ts +1 -2
  56. package/src/entry/SdCliElectron.ts +3 -3
  57. package/src/entry/SdCliProject.ts +12 -41
  58. package/src/index.ts +3 -0
  59. package/src/sd-cli.ts +3 -21
  60. package/src/utils/SdMemoryLoadResultCache.ts +44 -0
  61. package/src/utils/SdSourceFileCache.ts +6 -0
@@ -4,104 +4,104 @@ import path from "path";
4
4
  import esbuildPluginTsc from "esbuild-plugin-tsc";
5
5
 
6
6
  export class SdTsBundler {
7
- private _context?: esbuild.BuildContext;
7
+ #context?: esbuild.BuildContext;
8
8
 
9
- public constructor(private readonly _opt: {
9
+ constructor(private readonly _opt: {
10
10
  dev: boolean;
11
11
  pkgPath: string;
12
12
  entryPoints: string[];
13
- // external?: string[];
13
+ external?: string[];
14
14
  }) {
15
15
  }
16
16
 
17
- public async bundleAsync(): Promise<ISdCliPackageBuildResult[]> {
18
- if (!this._context) {
19
- const options = this.getOptions();
20
- this._context = await esbuild.context(options);
21
- }
22
- const results = await this._context.rebuild();
23
- return this._convertResults(results);
24
- }
25
-
26
- public getOptions(): esbuild.BuildOptions {
27
- return {
28
- entryPoints: this._opt.entryPoints,
29
- keepNames: true,
30
- bundle: true,
31
- sourcemap: this._opt.dev,
32
- target: "node16",
33
- mainFields: ['es2020', 'es2015', 'module', 'main'],
34
- conditions: ["es2020", "es2015", "module"],
35
- tsconfig: path.resolve(this._opt.pkgPath, "tsconfig.json"),
36
- write: true,
37
- outdir: path.resolve(this._opt.pkgPath, "dist"),
38
- format: "esm",
39
- resolveExtensions: [".js", ".mjs", ".cjs", ".ts"],
40
- preserveSymlinks: false,
41
- loader: {
42
- ".png": "file",
43
- ".jpeg": "file",
44
- ".jpg": "file",
45
- ".jfif": "file",
46
- ".gif": "file",
47
- ".svg": "file",
48
- ".woff": "file",
49
- ".woff2": "file",
50
- ".ttf": "file",
51
- ".eot": "file",
52
- ".ico": "file",
53
- ".otf": "file",
54
- ".csv": "file",
55
- ".xlsx": "file",
56
- ".xls": "file",
57
- ".pptx": "file",
58
- ".ppt": "file",
59
- ".docx": "file",
60
- ".doc": "file",
61
- ".zip": "file",
62
- ".pfx": "file",
63
- ".pkl": "file"
64
- },
65
- platform: "node",
66
- logLevel: "silent",
67
- packages: "external",
68
- // external: this._opt.external,
69
- banner: {
70
- js: `
17
+ async bundleAsync(): Promise<{
18
+ filePaths: string[];
19
+ results: ISdCliPackageBuildResult[];
20
+ }> {
21
+ if (!this.#context) {
22
+ this.#context = await esbuild.context({
23
+ entryPoints: this._opt.entryPoints,
24
+ keepNames: true,
25
+ bundle: true,
26
+ sourcemap: this._opt.dev,
27
+ target: "node16",
28
+ mainFields: ['es2020', 'es2015', 'module', 'main'],
29
+ conditions: ["es2020", "es2015", "module"],
30
+ tsconfig: path.resolve(this._opt.pkgPath, "tsconfig.json"),
31
+ write: true,
32
+ metafile: true,
33
+ outdir: path.resolve(this._opt.pkgPath, "dist"),
34
+ format: "esm",
35
+ resolveExtensions: [".js", ".mjs", ".cjs", ".ts"],
36
+ preserveSymlinks: false,
37
+ loader: {
38
+ ".png": "file",
39
+ ".jpeg": "file",
40
+ ".jpg": "file",
41
+ ".jfif": "file",
42
+ ".gif": "file",
43
+ ".svg": "file",
44
+ ".woff": "file",
45
+ ".woff2": "file",
46
+ ".ttf": "file",
47
+ ".eot": "file",
48
+ ".ico": "file",
49
+ ".otf": "file",
50
+ ".csv": "file",
51
+ ".xlsx": "file",
52
+ ".xls": "file",
53
+ ".pptx": "file",
54
+ ".ppt": "file",
55
+ ".docx": "file",
56
+ ".doc": "file",
57
+ ".zip": "file",
58
+ ".pfx": "file",
59
+ ".pkl": "file"
60
+ },
61
+ platform: "node",
62
+ logLevel: "silent",
63
+ // packages: "external",
64
+ external: this._opt.external,
65
+ banner: {
66
+ js: `
71
67
  import __path__ from 'path';
72
68
  import { fileURLToPath as __fileURLToPath__ } from 'url';
73
- // import { createRequire as __createRequire__ } from 'module';
74
- //
75
- // const require = __createRequire__(import.meta.url);
69
+ import { createRequire as __createRequire__ } from 'module';
70
+
71
+ const require = __createRequire__(import.meta.url);
76
72
  const __filename = __fileURLToPath__(import.meta.url);
77
73
  const __dirname = __path__.dirname(__filename);`.trim()
78
- },
79
- plugins: [
80
- esbuildPluginTsc()
74
+ },
75
+ plugins: [
76
+ esbuildPluginTsc()
77
+ ]
78
+ });
79
+ }
80
+
81
+ const result = await this.#context.rebuild();
82
+
83
+ return {
84
+ filePaths: Object.keys(result.metafile!.inputs).map(item => path.resolve(process.cwd(), item)),
85
+ results: [
86
+ ...result.warnings.map((warn) => ({
87
+ type: "build" as const,
88
+ filePath: warn.location?.file !== undefined ? path.resolve(warn.location.file) : undefined,
89
+ line: warn.location?.line,
90
+ char: warn.location?.column,
91
+ code: undefined,
92
+ severity: "warning" as const,
93
+ message: warn.text
94
+ })),
95
+ ...result.errors.map((err) => ({
96
+ type: "build" as const,
97
+ filePath: err.location?.file !== undefined ? path.resolve(err.location.file) : undefined,
98
+ line: err.location?.line,
99
+ char: err.location?.column !== undefined ? err.location.column + 1 : undefined,
100
+ code: undefined,
101
+ severity: "error" as const,
102
+ message: err.text
103
+ }))
81
104
  ]
82
105
  };
83
106
  }
84
-
85
- private _convertResults(result: esbuild.BuildResult): ISdCliPackageBuildResult[] {
86
- return [
87
- ...result.warnings.map((warn) => ({
88
- type: "build" as const,
89
- filePath: warn.location?.file !== undefined ? path.resolve(warn.location.file) : undefined,
90
- line: warn.location?.line,
91
- char: warn.location?.column,
92
- code: undefined,
93
- severity: "warning" as const,
94
- message: warn.text
95
- })),
96
- ...result.errors.map((err) => ({
97
- type: "build" as const,
98
- filePath: err.location?.file !== undefined ? path.resolve(err.location.file) : undefined,
99
- line: err.location?.line,
100
- char: err.location?.column !== undefined ? err.location.column + 1 : undefined,
101
- code: undefined,
102
- severity: "error" as const,
103
- message: err.text
104
- }))
105
- ];
106
- }
107
107
  }
@@ -99,6 +99,7 @@ export class SdTsCompiler {
99
99
  }
100
100
 
101
101
  public async buildAsync(): Promise<{
102
+ filePaths: string[];
102
103
  affectedFilePaths: string[];
103
104
  results: ISdCliPackageBuildResult[];
104
105
  }> {
@@ -290,7 +291,11 @@ export class SdTsCompiler {
290
291
  const buildResults = diagnostics.map((item) => SdCliBuildResultUtil.convertFromTsDiag(item, this._opt.emit ? "build" : "check"));
291
292
 
292
293
  return {
293
- affectedFilePaths: affectedFilePaths.filter((item) => !item.endsWith(".scss")),
294
+ filePaths: [
295
+ ...Array.from(this._styleDepsCache.keys()),
296
+ ...this._builder.getSourceFiles().map(item => path.resolve(item.fileName))
297
+ ],
298
+ affectedFilePaths: affectedFilePaths,
294
299
  results: buildResults
295
300
  };
296
301
  }
@@ -1,13 +1,13 @@
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, Wait} from "@simplysm/sd-core-common";
4
+ import {FunctionQueue} from "@simplysm/sd-core-common";
5
5
  import path from "path";
6
6
  import {SdNgBundler} from "../build-tools/SdNgBundler";
7
7
  import {SdLinter} from "../build-tools/SdLinter";
8
8
  import {SdCliCordova} from "../build-tools/SdCliCordova";
9
+ import {SdCliNgRoutesFileGenerator} from "../build-tools/SdCliNgRoutesFileGenerator";
9
10
 
10
- // TODO: ROUTER 자동생성
11
11
  export class SdCliClientBuilder extends EventEmitter {
12
12
  private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdCliClientBuilder"]);
13
13
  private readonly _pkgConf: ISdCliClientPackageConfig;
@@ -31,7 +31,14 @@ export class SdCliClientBuilder extends EventEmitter {
31
31
  this._debug("dist 초기화...");
32
32
  await FsUtil.removeAsync(path.resolve(this._pkgPath, "dist"));
33
33
 
34
- return await this._runAsync({dev: false, genConf: true});
34
+ this._debug(`GEN index.ts...`);
35
+ await SdCliNgRoutesFileGenerator.runAsync(this._pkgPath);
36
+
37
+ this._debug("GEN .config...");
38
+ const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
39
+ await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
40
+
41
+ return await this._runAsync({dev: false});
35
42
  }
36
43
 
37
44
  public async watchAsync(): Promise<void> {
@@ -40,16 +47,20 @@ export class SdCliClientBuilder extends EventEmitter {
40
47
  this._debug("dist 초기화...");
41
48
  await FsUtil.removeAsync(path.resolve(this._pkgPath, "dist"));
42
49
 
43
- const result = await this._runAsync({dev: true, genConf: true});
50
+ this._debug(`WATCH GEN index.ts...`);
51
+ await SdCliNgRoutesFileGenerator.watchAsync(this._pkgPath);
52
+
53
+ this._debug("GEN .config...");
54
+ const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
55
+ await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
56
+
57
+ const result = await this._runAsync({dev: true});
44
58
  this.emit("complete", result);
45
59
 
46
60
  this._debug("WATCH...");
47
61
  const fnQ = new FunctionQueue();
48
62
  const watcher = SdFsWatcher
49
- .watch([
50
- ...result.watchFilePaths,
51
- path.resolve(this._pkgPath, "src/**/*.*")
52
- ])
63
+ .watch(result.watchFilePaths)
53
64
  .onChange({delay: 100}, (changeInfos) => {
54
65
  for (const builder of this._builders!) {
55
66
  builder.removeCache(changeInfos.map((item) => item.path));
@@ -58,7 +69,7 @@ export class SdCliClientBuilder extends EventEmitter {
58
69
  fnQ.runLast(async () => {
59
70
  this.emit("change");
60
71
 
61
- const watchResult = await this._runAsync({dev: true, genConf: false});
72
+ const watchResult = await this._runAsync({dev: true});
62
73
  this.emit("complete", watchResult);
63
74
 
64
75
  watcher.add(watchResult.watchFilePaths);
@@ -68,34 +79,39 @@ export class SdCliClientBuilder extends EventEmitter {
68
79
 
69
80
  private async _runAsync(opt: {
70
81
  dev: boolean;
71
- genConf: boolean;
72
82
  }): Promise<{
73
83
  watchFilePaths: string[];
74
84
  affectedFilePaths: string[];
75
85
  buildResults: ISdCliPackageBuildResult[];
76
86
  }> {
77
- const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as (keyof ISdCliClientPackageConfig["builder"])[]);
87
+ const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as ("web" | "electron" | "cordova")[]);
78
88
  if (this._pkgConf.builder?.cordova && !this._cordova) {
79
89
  this._debug("CORDOVA 준비...");
80
90
  this._cordova = new SdCliCordova({
81
91
  pkgPath: this._pkgPath,
82
92
  config: this._pkgConf.builder.cordova,
83
- cordovaPath: path.resolve(this._pkgPath, ".cache/cordova")
93
+ cordovaPath: path.resolve(this._pkgPath, ".cordova")
84
94
  });
85
95
  await this._cordova.initializeAsync();
86
96
  }
87
97
 
88
- this._debug(`BUILD 준비...`);
89
- this._builders = this._builders ?? builderTypes.map((builderType) => new SdNgBundler({
90
- dev: opt.dev,
91
- builderType: builderType,
92
- pkgPath: this._pkgPath,
93
- cordovaPlatforms: builderType === "cordova" ? Object.keys(this._pkgConf.builder!.cordova!.platform ?? {browser: {}}) : undefined,
94
- outputPath: builderType === "web" ? path.resolve(this._pkgPath, "dist")
95
- : builderType === "electron" ? path.resolve(this._pkgPath, ".cache/electron/src")
96
- : builderType === "cordova" && !opt.dev ? path.resolve(this._pkgPath, ".cache/cordova/www")
97
- : path.resolve(this._pkgPath, "dist", builderType)
98
- }));
98
+ if (!this._builders) {
99
+ this._debug(`BUILD 준비...`);
100
+ this._builders = builderTypes.map((builderType) => new SdNgBundler({
101
+ dev: opt.dev,
102
+ builderType: builderType,
103
+ pkgPath: this._pkgPath,
104
+ cordovaPlatforms: builderType === "cordova" ? Object.keys(this._pkgConf.builder!.cordova!.platform ?? {browser: {}}) : undefined,
105
+ outputPath: builderType === "web" ? path.resolve(this._pkgPath, "dist")
106
+ : builderType === "electron" ? path.resolve(this._pkgPath, ".electron/src")
107
+ : builderType === "cordova" && !opt.dev ? path.resolve(this._pkgPath, ".cordova/www")
108
+ : path.resolve(this._pkgPath, "dist", builderType),
109
+ env: {
110
+ ...this._pkgConf.env,
111
+ ...this._pkgConf.builder?.[builderType]?.env
112
+ }
113
+ }));
114
+ }
99
115
 
100
116
  this._debug(`BUILD & CHECK...`);
101
117
  const buildResults = await Promise.all(this._builders.map((builder) => builder.bundleAsync()));
@@ -104,34 +120,37 @@ export class SdCliClientBuilder extends EventEmitter {
104
120
  const results = buildResults.mapMany((item) => item.results).distinct();
105
121
 
106
122
  this._debug(`LINT...`);
107
- const lintResults = await SdLinter.lintAsync(affectedFilePaths, this._pkgPath);
108
-
109
- if (opt.genConf) {
110
- this._debug("GEN .config...");
111
- if (opt.dev && this._pkgConf.server !== undefined) {
112
- const serverDistPath = path.resolve(this._pkgPath, "../", this._pkgConf.server, "dist");
113
- await Wait.until(() => FsUtil.exists(serverDistPath));
114
- await FsUtil.writeJsonAsync(path.resolve(serverDistPath, "www", path.basename(this._pkgPath), ".config.json"), this._pkgConf.configs ?? {}, {space: 2});
115
- }
116
- else {
117
- await FsUtil.writeJsonAsync(path.resolve(this._pkgPath, "dist/.config.json"), this._pkgConf.configs ?? {}, {space: 2});
118
- }
119
- }
123
+ const lintResults = await SdLinter.lintAsync(
124
+ affectedFilePaths,
125
+ this._pkgPath
126
+ );
120
127
 
121
128
  if (!opt.dev && this._cordova) {
122
129
  this._debug("CORDOVA BUILD...");
123
- await this._cordova.buildAsync(path.resolve(this._pkgPath, ".cache/cordova"));
130
+ await this._cordova.buildAsync(path.resolve(this._pkgPath, "dist"));
124
131
  }
125
132
 
133
+ this._debug(`빌드 완료`);
126
134
  const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
127
135
  .mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
128
- const watchFilePaths = filePaths
129
- .filter((item) =>
130
- PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
131
- localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
132
- );
136
+ /*const watchFilePaths = filePaths
137
+ .map((item) => {
138
+ if (PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../"))) {
139
+ return path.resolve(this._pkgPath, "..", path.relative(path.resolve(this._pkgPath, "../"), item).split("\\").slice(0, 2).join("/"), "**!/!*.*");
140
+ }
133
141
 
134
- this._debug(`빌드 완료`);
142
+ const localUpdatePath = localUpdatePaths.single((lu) => PathUtil.isChildPath(item, lu));
143
+ if (localUpdatePath != null) {
144
+ return path.resolve(localUpdatePath, path.relative(localUpdatePath, item).split("\\").slice(0, 1).join("/"), "**!/!*.*");
145
+ }
146
+
147
+ return undefined;
148
+ }).filterExists().distinct();
149
+ console.log(watchFilePaths);*/
150
+ const watchFilePaths = filePaths.filter(item =>
151
+ PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
152
+ localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
153
+ );
135
154
  return {
136
155
  watchFilePaths: watchFilePaths,
137
156
  affectedFilePaths: affectedFilePaths,
@@ -1,19 +1,28 @@
1
1
  import {EventEmitter} from "events";
2
- import {FsUtil, Logger, SdFsWatcher} from "@simplysm/sd-core-node";
3
- import {INpmConfig, ISdCliBuilderResult, ISdCliConfig, ISdCliServerPackageConfig} from "../commons";
2
+ import {FsUtil, Logger, PathUtil, SdFsWatcher} from "@simplysm/sd-core-node";
3
+ import {
4
+ INpmConfig,
5
+ ISdCliBuilderResult,
6
+ ISdCliConfig,
7
+ ISdCliPackageBuildResult,
8
+ ISdCliServerPackageConfig,
9
+ ITsConfig
10
+ } from "../commons";
4
11
  import path from "path";
5
12
  import {SdTsCompiler} from "../build-tools/SdTsCompiler";
6
13
  import {SdLinter} from "../build-tools/SdLinter";
7
- import {FunctionQueue, ObjectUtil} from "@simplysm/sd-core-common";
14
+ import {FunctionQueue, ObjectUtil, StringUtil} from "@simplysm/sd-core-common";
8
15
  import {SdTsBundler} from "../build-tools/SdTsBundler";
9
16
 
10
17
  export class SdCliServerBuilder extends EventEmitter {
11
18
  private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdCliServerBuilder"]);
12
19
  private readonly _pkgConf: ISdCliServerPackageConfig;
20
+ private _builder?: SdTsBundler;
21
+ private _checker?: SdTsCompiler;
22
+ private _extModules?: { name: string; exists: boolean }[];
13
23
 
14
24
  public constructor(private readonly _projConf: ISdCliConfig,
15
- private readonly _pkgPath: string,
16
- private readonly _withLint: boolean) {
25
+ private readonly _pkgPath: string) {
17
26
  super();
18
27
  this._pkgConf = this._projConf.packages[path.basename(_pkgPath)] as ISdCliServerPackageConfig;
19
28
  }
@@ -26,7 +35,7 @@ export class SdCliServerBuilder extends EventEmitter {
26
35
  }
27
36
 
28
37
  public async watchAsync(): Promise<void> {
29
- // const extModules = await this._getExternalModulesAsync();
38
+ this.emit("change");
30
39
 
31
40
  this._debug("dist 초기화...");
32
41
  await FsUtil.removeAsync(path.resolve(this._pkgPath, "dist"));
@@ -35,58 +44,28 @@ export class SdCliServerBuilder extends EventEmitter {
35
44
  const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
36
45
  await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
37
46
 
38
- this._debug(`BUILD 준비...`);
39
- const builder = new SdTsBundler({
40
- dev: false,
41
- pkgPath: this._pkgPath,
42
- entryPoints: [
43
- path.resolve(this._pkgPath, "src/main.ts")
44
- ],
45
- // external: extModules.map((item) => item.name)
46
- });
47
-
48
- const checker = new SdTsCompiler({
49
- pkgPath: this._pkgPath,
50
- emit: false,
51
- emitDts: false,
52
- globalStyle: false
53
- });
47
+ const result = await this._runAsync({dev: true});
48
+ this.emit("complete", result);
54
49
 
55
50
  this._debug("WATCH...");
56
51
  const fnQ = new FunctionQueue();
57
- SdFsWatcher
58
- .watch([
59
- path.resolve(this._pkgPath, "src/**/*.*")
60
- ], {
61
- ignoreInitial: false
62
- })
63
- .onChange({
64
- delay: 100
65
- }, () => {
52
+ const watcher = SdFsWatcher
53
+ .watch(result.watchFilePaths)
54
+ .onChange({delay: 100}, () => {
66
55
  fnQ.runLast(async () => {
67
56
  this.emit("change");
68
57
 
69
- this._debug(`BUILD...`);
70
- const buildResults = await builder.bundleAsync();
71
-
72
- this._debug("CHECK...");
73
- const checkResult = await checker.buildAsync();
74
-
75
- this._debug(`LINT...`);
76
- const lintResults = !this._withLint ? [] : await SdLinter.lintAsync(checkResult.affectedFilePaths, checker.program);
58
+ const watchResult = await this._runAsync({dev: true});
59
+ this.emit("complete", watchResult);
77
60
 
78
- this._debug(`빌드 완료`);
79
- this.emit("complete", {
80
- affectedFilePaths: checkResult.affectedFilePaths,
81
- buildResults: [...buildResults, ...checkResult.results, ...lintResults]
82
- });
61
+ watcher.add(watchResult.watchFilePaths);
83
62
  });
84
63
  });
85
64
  }
86
65
 
87
66
  public async buildAsync(): Promise<ISdCliBuilderResult> {
88
67
  const npmConfig = (await FsUtil.readJsonAsync(path.resolve(this._pkgPath, "package.json"))) as INpmConfig;
89
- // const extModules = await this._getExternalModulesAsync();
68
+ const extModules = await this._getExternalModulesAsync();
90
69
 
91
70
  this._debug("dist 초기화...");
92
71
  await FsUtil.removeAsync(path.resolve(this._pkgPath, "dist"));
@@ -97,13 +76,13 @@ export class SdCliServerBuilder extends EventEmitter {
97
76
 
98
77
  this._debug("GEN package.json...");
99
78
  {
100
- // const deps = extModules.filter((item) => item.exists).map((item) => item.name);
79
+ const deps = extModules.filter((item) => item.exists).map((item) => item.name);
101
80
 
102
81
  const distNpmConfig = ObjectUtil.clone(npmConfig);
103
- // distNpmConfig.dependencies = {};
104
- // for (const dep of deps) {
105
- // distNpmConfig.dependencies[dep] = "*";
106
- // }
82
+ distNpmConfig.dependencies = {};
83
+ for (const dep of deps) {
84
+ distNpmConfig.dependencies[dep] = "*";
85
+ }
107
86
  delete distNpmConfig.optionalDependencies;
108
87
  delete distNpmConfig.devDependencies;
109
88
  delete distNpmConfig.peerDependencies;
@@ -177,17 +156,29 @@ export class SdCliServerBuilder extends EventEmitter {
177
156
  `.trim());
178
157
  }
179
158
 
159
+ return await this._runAsync({dev: false});
160
+ }
161
+
162
+ private async _runAsync(opt: { dev: boolean }): Promise<{
163
+ watchFilePaths: string[];
164
+ affectedFilePaths: string[];
165
+ buildResults: ISdCliPackageBuildResult[];
166
+ }> {
180
167
  this._debug(`BUILD 준비...`);
181
- const builder = new SdTsBundler({
182
- dev: true,
168
+
169
+ this._extModules = this._extModules ?? await this._getExternalModulesAsync();
170
+
171
+ const tsConfig = FsUtil.readJson(path.resolve(this._pkgPath, "tsconfig.json")) as ITsConfig;
172
+ this._builder = this._builder ?? new SdTsBundler({
173
+ dev: opt.dev,
183
174
  pkgPath: this._pkgPath,
184
- entryPoints: [
175
+ entryPoints: tsConfig.files ? tsConfig.files.map((item) => path.resolve(this._pkgPath, item)) : [
185
176
  path.resolve(this._pkgPath, "src/main.ts")
186
177
  ],
187
- // external: extModules.map((item) => item.name)
178
+ external: this._extModules.map((item) => item.name)
188
179
  });
189
180
 
190
- const checker = new SdTsCompiler({
181
+ this._checker = this._checker ?? new SdTsCompiler({
191
182
  pkgPath: this._pkgPath,
192
183
  emit: false,
193
184
  emitDts: false,
@@ -195,22 +186,32 @@ export class SdCliServerBuilder extends EventEmitter {
195
186
  });
196
187
 
197
188
  this._debug(`BUILD...`);
198
- const buildResults = await builder.bundleAsync();
189
+ const buildResult = await this._builder.bundleAsync();
199
190
 
200
191
  this._debug("CHECK...");
201
- const checkResult = await checker.buildAsync();
192
+ const checkResult = await this._checker.buildAsync();
202
193
 
203
194
  this._debug(`LINT...`);
204
- const lintResults = !this._withLint ? [] : await SdLinter.lintAsync(checkResult.affectedFilePaths, checker.program);
195
+ const lintResults = await SdLinter.lintAsync(checkResult.affectedFilePaths, this._checker.program);
205
196
 
206
197
  this._debug(`빌드 완료`);
198
+ const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
199
+ .mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
200
+ const watchFilePaths = [
201
+ ...buildResult.filePaths,
202
+ ...checkResult.filePaths,
203
+ ].filter(item =>
204
+ PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
205
+ localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
206
+ );
207
207
  return {
208
+ watchFilePaths,
208
209
  affectedFilePaths: checkResult.affectedFilePaths,
209
- buildResults: [...buildResults, ...checkResult.results, ...lintResults]
210
+ buildResults: [...buildResult.results, ...checkResult.results, ...lintResults]
210
211
  };
211
212
  }
212
213
 
213
- /*private async _getExternalModulesAsync(): Promise<{
214
+ private async _getExternalModulesAsync(): Promise<{
214
215
  name: string;
215
216
  exists: boolean
216
217
  }[]> {
@@ -245,7 +246,7 @@ export class SdCliServerBuilder extends EventEmitter {
245
246
  continue;
246
247
  }
247
248
 
248
- if (FsUtil.glob(path.resolve(modulePath, "**!/binding.gyp")).length > 0) {
249
+ if (FsUtil.glob(path.resolve(modulePath, "binding.gyp")).length > 0) {
249
250
  results.push({
250
251
  name: moduleName,
251
252
  exists: true
@@ -275,7 +276,7 @@ export class SdCliServerBuilder extends EventEmitter {
275
276
  continue;
276
277
  }
277
278
 
278
- if (FsUtil.glob(path.resolve(optModulePath, "**!/binding.gyp")).length > 0) {
279
+ if (FsUtil.glob(path.resolve(optModulePath, "binding.gyp")).length > 0) {
279
280
  results.push({
280
281
  name: optModuleName,
281
282
  exists: true
@@ -296,7 +297,7 @@ export class SdCliServerBuilder extends EventEmitter {
296
297
  await fn(this._pkgPath);
297
298
 
298
299
  return results;
299
- }*/
300
+ }
300
301
 
301
302
  private _debug(msg: string): void {
302
303
  this._logger.debug(`[${path.basename(this._pkgPath)}] ${msg}`);