@simplysm/sd-cli 7.0.50 → 7.0.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +7 -0
- package/dist/bin/sd-cli.mjs +2 -2
- package/dist/build-tool/SdCliCacheCompilerHost.mjs +8 -3
- package/dist/build-tool/SdCliNgCacheCompilerHost.mjs +1 -1
- package/dist/build-tool/SdCliPackageLinter.mjs +1 -1
- package/dist/builder/SdCliClientBuilder.mjs +40 -10
- package/dist/builder/SdCliJsLibBuilder.mjs +3 -3
- package/dist/builder/SdCliServerBuilder.mjs +33 -22
- package/dist/builder/SdCliTsLibBuilder.mjs +3 -3
- package/dist/entry-points/SdCliIndexFileGenerator.mjs +62 -0
- package/dist/entry-points/SdCliLocalUpdate.mjs +9 -4
- package/dist/entry-points/SdCliNpm.mjs +1 -1
- package/dist/entry-points/SdCliPrepare.mjs +1 -1
- package/dist/entry-points/SdCliWorkspace.mjs +23 -4
- package/dist/packages/SdCliPackage.mjs +4 -3
- package/dist/utils/SdCliBuildResultUtil.mjs +3 -3
- package/dist/utils/SdCliConfigUtil.mjs +2 -2
- package/lib/ts-node-esm-paths.mjs +2 -2
- package/package.json +9 -8
- package/src/bin/sd-cli.ts +1 -1
- package/src/build-tool/SdCliCacheCompilerHost.ts +8 -2
- package/src/build-tool/SdCliNgCacheCompilerHost.ts +1 -1
- package/src/build-tool/SdCliPackageLinter.ts +1 -1
- package/src/builder/SdCliClientBuilder.ts +52 -11
- package/src/builder/SdCliJsLibBuilder.ts +2 -2
- package/src/builder/SdCliServerBuilder.ts +34 -21
- package/src/builder/SdCliTsLibBuilder.ts +2 -2
- package/src/commons.ts +8 -3
- package/src/entry-points/SdCliIndexFileGenerator.ts +79 -0
- package/src/entry-points/SdCliLocalUpdate.ts +8 -3
- package/src/entry-points/SdCliNpm.ts +1 -1
- package/src/entry-points/SdCliPrepare.ts +1 -1
- package/src/entry-points/SdCliWorkspace.ts +28 -4
- package/src/packages/SdCliPackage.ts +4 -2
- package/src/utils/SdCliBuildResultUtil.ts +2 -2
- package/src/utils/SdCliConfigUtil.ts +2 -2
- package/tsconfig-build.json +2 -1
- package/tsconfig.json +10 -4
- package/dist/bin/sd-cli.d.ts +0 -2
- package/dist/build-tool/SdCliCacheCompilerHost.d.ts +0 -10
- package/dist/build-tool/SdCliNgCacheCompilerHost.d.ts +0 -11
- package/dist/build-tool/SdCliPackageLinter.d.ts +0 -8
- package/dist/builder/SdCliClientBuilder.d.ts +0 -20
- package/dist/builder/SdCliJsLibBuilder.d.ts +0 -14
- package/dist/builder/SdCliServerBuilder.d.ts +0 -24
- package/dist/builder/SdCliTsLibBuilder.d.ts +0 -29
- package/dist/commons.d.ts +0 -58
- package/dist/entry-points/SdCliLocalUpdate.d.ts +0 -13
- package/dist/entry-points/SdCliNpm.d.ts +0 -6
- package/dist/entry-points/SdCliPrepare.d.ts +0 -5
- package/dist/entry-points/SdCliWorkspace.d.ts +0 -27
- package/dist/packages/SdCliPackage.d.ts +0 -23
- package/dist/utils/SdCliBuildResultUtil.d.ts +0 -9
- package/dist/utils/SdCliConfigUtil.d.ts +0 -7
- package/dist/utils/SdCliNpmConfigUtil.d.ts +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { INpmConfig, ISdCliClientPackageConfig, ISdCliPackageBuildResult } from "../commons";
|
|
1
|
+
import { INpmConfig, ISdCliClientPackageConfig, ISdCliPackageBuildResult, ITsconfig } from "../commons";
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
|
-
import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core
|
|
3
|
+
import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core-node";
|
|
4
4
|
import webpack from "webpack";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import ts from "typescript";
|
|
@@ -32,6 +32,8 @@ import { ESLint } from "eslint";
|
|
|
32
32
|
import { TransferSizePlugin } from "@angular-devkit/build-angular/src/webpack/plugins/transfer-size-plugin";
|
|
33
33
|
import { CssOptimizerPlugin } from "@angular-devkit/build-angular/src/webpack/plugins/css-optimizer-plugin";
|
|
34
34
|
import browserslist from "browserslist";
|
|
35
|
+
import { augmentAppWithServiceWorker } from "@angular-devkit/build-angular/src/utils/service-worker";
|
|
36
|
+
import { StringUtil } from "@simplysm/sd-core-common";
|
|
35
37
|
import LintResult = ESLint.LintResult;
|
|
36
38
|
|
|
37
39
|
export class SdCliClientBuilder extends EventEmitter {
|
|
@@ -48,8 +50,8 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
48
50
|
|
|
49
51
|
// tsconfig
|
|
50
52
|
this._tsconfigFilePath = path.resolve(this._rootPath, "tsconfig-build.json");
|
|
51
|
-
const tsconfig = FsUtil.readJson(this._tsconfigFilePath);
|
|
52
|
-
this._parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._rootPath);
|
|
53
|
+
const tsconfig = FsUtil.readJson(this._tsconfigFilePath) as ITsconfig;
|
|
54
|
+
this._parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._rootPath, tsconfig.angularCompilerOptions);
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
public override on(event: "change", listener: () => void): this;
|
|
@@ -78,11 +80,20 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
78
80
|
return;
|
|
79
81
|
});
|
|
80
82
|
|
|
81
|
-
compiler.hooks.done.tap(this.constructor.name, (stats) => {
|
|
83
|
+
compiler.hooks.done.tap(this.constructor.name, async (stats) => {
|
|
82
84
|
// 결과 반환
|
|
83
85
|
const results = SdCliBuildResultUtil.convertFromWebpackStats(stats);
|
|
84
86
|
this.emit("complete", results);
|
|
85
87
|
|
|
88
|
+
// .config.json 파일 쓰기
|
|
89
|
+
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
90
|
+
const packageKey = npmConfig.name.split("/").last()!;
|
|
91
|
+
|
|
92
|
+
const configDistPath = !StringUtil.isNullOrEmpty(this._config.server)
|
|
93
|
+
? path.resolve(this._workspaceRootPath, "packages", this._config.server, "dist/www", packageKey, ".config.json")
|
|
94
|
+
: path.resolve(this._parsedTsconfig.options.outDir!, ".config.json");
|
|
95
|
+
await FsUtil.writeFileAsync(configDistPath, JSON.stringify(this._config.configs ?? {}, undefined, 2));
|
|
96
|
+
|
|
86
97
|
// 마무리
|
|
87
98
|
this._logger.debug("Webpack 빌드 완료");
|
|
88
99
|
resolve([devMiddleware, hotMiddleware]);
|
|
@@ -122,15 +133,38 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
122
133
|
});
|
|
123
134
|
});
|
|
124
135
|
|
|
136
|
+
// .config.json 파일 쓰기
|
|
137
|
+
const targetPath = path.resolve(this._parsedTsconfig.options.outDir!, ".config.json");
|
|
138
|
+
await FsUtil.writeFileAsync(targetPath, JSON.stringify(this._config.configs ?? {}, undefined, 2));
|
|
139
|
+
|
|
140
|
+
// service-worker 처리
|
|
141
|
+
if (FsUtil.exists(path.resolve(this._rootPath, "ngsw-config.json"))) {
|
|
142
|
+
const packageKey = this._getNpmConfig(this._rootPath)!.name.split("/").last()!;
|
|
143
|
+
await augmentAppWithServiceWorker(
|
|
144
|
+
PathUtil.posix(path.relative(this._workspaceRootPath, this._rootPath)) as any,
|
|
145
|
+
PathUtil.posix(path.relative(this._workspaceRootPath, this._parsedTsconfig.options.outDir!)) as any,
|
|
146
|
+
`/${packageKey}/`,
|
|
147
|
+
PathUtil.posix(path.relative(this._workspaceRootPath, path.resolve(this._rootPath, "ngsw-config.json")))
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
125
151
|
// 마무리
|
|
126
152
|
this._logger.debug("Webpack 빌드 완료");
|
|
127
153
|
return buildResults;
|
|
128
154
|
}
|
|
129
155
|
|
|
156
|
+
private _getInternalModuleCachePaths(workspaceName: string): string[] {
|
|
157
|
+
return [
|
|
158
|
+
...FsUtil.findAllParentChildDirPaths("node_modules/*/package.json", this._rootPath, this._workspaceRootPath),
|
|
159
|
+
...FsUtil.findAllParentChildDirPaths(`node_modules/!(@simplysm|@${workspaceName})/*/package.json`, this._rootPath, this._workspaceRootPath),
|
|
160
|
+
].map((p) => path.dirname(p));
|
|
161
|
+
}
|
|
162
|
+
|
|
130
163
|
private _getWebpackConfig(watch: boolean): webpack.Configuration {
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
164
|
+
const workspaceNpmConfig = this._getNpmConfig(this._workspaceRootPath)!;
|
|
165
|
+
const workspaceName = workspaceNpmConfig.name;
|
|
166
|
+
|
|
167
|
+
const internalModuleCachePaths = watch ? this._getInternalModuleCachePaths(workspaceName) : undefined;
|
|
134
168
|
|
|
135
169
|
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
136
170
|
const pkgVersion = npmConfig.version;
|
|
@@ -157,7 +191,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
157
191
|
profile: false,
|
|
158
192
|
resolve: {
|
|
159
193
|
roots: [this._rootPath],
|
|
160
|
-
extensions: [".ts", ".tsx", ".mjs", ".js"],
|
|
194
|
+
extensions: [".ts", ".tsx", ".mjs", ".cjs", ".js"],
|
|
161
195
|
symlinks: true,
|
|
162
196
|
modules: [this._workspaceRootPath, "node_modules"],
|
|
163
197
|
mainFields: ["es2015", "browser", "module", "main"],
|
|
@@ -312,7 +346,10 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
312
346
|
loader: "source-map-loader",
|
|
313
347
|
options: {
|
|
314
348
|
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
315
|
-
|
|
349
|
+
const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
|
|
350
|
+
return !resourcePath.includes("node_modules")
|
|
351
|
+
|| (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
|
|
352
|
+
|| workspaceRegex.test(resourcePath);
|
|
316
353
|
}
|
|
317
354
|
}
|
|
318
355
|
}
|
|
@@ -380,7 +417,11 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
380
417
|
loader: HmrLoader,
|
|
381
418
|
include: [mainFilePath]
|
|
382
419
|
}
|
|
383
|
-
] : []
|
|
420
|
+
] : [],
|
|
421
|
+
{
|
|
422
|
+
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico|otf|xlsx?|pptx?|docx?|zip|pfx|pkl)$/,
|
|
423
|
+
type: "asset/resource"
|
|
424
|
+
}
|
|
384
425
|
]
|
|
385
426
|
},
|
|
386
427
|
plugins: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ISdCliPackageBuildResult } from "../commons";
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
|
-
import { FsUtil, Logger, SdFsWatcher } from "@simplysm/sd-core
|
|
4
|
-
import
|
|
3
|
+
import { FsUtil, Logger, SdFsWatcher } from "@simplysm/sd-core-node";
|
|
4
|
+
import path from "path";
|
|
5
5
|
import { SdCliPackageLinter } from "../build-tool/SdCliPackageLinter";
|
|
6
6
|
|
|
7
7
|
export class SdCliJsLibBuilder extends EventEmitter {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { INpmConfig, ISdCliPackageBuildResult, ISdCliServerPackageConfig } from "../commons";
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
|
-
import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core
|
|
3
|
+
import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core-node";
|
|
4
4
|
import webpack from "webpack";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import ts from "typescript";
|
|
@@ -9,7 +9,7 @@ import { ErrorInfo } from "ts-loader/dist/interfaces";
|
|
|
9
9
|
import os from "os";
|
|
10
10
|
import { ESLint } from "eslint";
|
|
11
11
|
import TerserPlugin from "terser-webpack-plugin";
|
|
12
|
-
import { ObjectUtil, StringUtil } from "@simplysm/sd-core
|
|
12
|
+
import { ObjectUtil, StringUtil } from "@simplysm/sd-core-common";
|
|
13
13
|
import ESLintWebpackPlugin from "eslint-webpack-plugin";
|
|
14
14
|
import CopyWebpackPlugin from "copy-webpack-plugin";
|
|
15
15
|
import { LicenseWebpackPlugin } from "license-webpack-plugin";
|
|
@@ -46,8 +46,8 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
46
46
|
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
47
47
|
|
|
48
48
|
// 빌드 준비
|
|
49
|
-
const
|
|
50
|
-
const webpackConfig = this._getWebpackConfig(true,
|
|
49
|
+
const extModules = this._getExternalModules();
|
|
50
|
+
const webpackConfig = this._getWebpackConfig(true, extModules.map((item) => item.name));
|
|
51
51
|
const compiler = webpack(webpackConfig);
|
|
52
52
|
await new Promise<void>((resolve, reject) => {
|
|
53
53
|
compiler.hooks.watchRun.tapAsync(this.constructor.name, (args, callback) => {
|
|
@@ -80,8 +80,8 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
80
80
|
|
|
81
81
|
// 빌드
|
|
82
82
|
this._logger.debug("Webpack 빌드 수행...");
|
|
83
|
-
const
|
|
84
|
-
const webpackConfig = this._getWebpackConfig(false,
|
|
83
|
+
const extModules = this._getExternalModules();
|
|
84
|
+
const webpackConfig = this._getWebpackConfig(false, extModules.map((item) => item.name));
|
|
85
85
|
const compiler = webpack(webpackConfig);
|
|
86
86
|
const buildResults = await new Promise<ISdCliPackageBuildResult[]>((resolve, reject) => {
|
|
87
87
|
compiler.run((err, stats) => {
|
|
@@ -106,7 +106,7 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
106
106
|
await this._writeDistIisConfigFileAsync();
|
|
107
107
|
|
|
108
108
|
// 배포용 package.json 파일 생성
|
|
109
|
-
await this._writeDistNpmConfigFileAsync(
|
|
109
|
+
await this._writeDistNpmConfigFileAsync(extModules.filter((item) => item.exists).map((item) => item.name));
|
|
110
110
|
|
|
111
111
|
// 마무리
|
|
112
112
|
this._logger.debug("Webpack 빌드 완료");
|
|
@@ -204,10 +204,18 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
204
204
|
);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
private _getInternalModuleCachePaths(workspaceName: string): string[] {
|
|
208
|
+
return [
|
|
209
|
+
...FsUtil.findAllParentChildDirPaths("node_modules/*/package.json", this._rootPath, this._workspaceRootPath),
|
|
210
|
+
...FsUtil.findAllParentChildDirPaths(`node_modules/!(@simplysm|@${workspaceName})/*/package.json`, this._rootPath, this._workspaceRootPath),
|
|
211
|
+
].map((p) => path.dirname(p));
|
|
212
|
+
}
|
|
213
|
+
|
|
207
214
|
private _getWebpackConfig(watch: boolean, extModuleNames: string[]): webpack.Configuration {
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
215
|
+
const workspaceNpmConfig = this._getNpmConfig(this._workspaceRootPath)!;
|
|
216
|
+
const workspaceName = workspaceNpmConfig.name;
|
|
217
|
+
|
|
218
|
+
const internalModuleCachePaths = watch ? this._getInternalModuleCachePaths(workspaceName) : undefined;
|
|
211
219
|
|
|
212
220
|
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
213
221
|
const pkgKey = npmConfig.name.split("/").last()!;
|
|
@@ -246,7 +254,9 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
246
254
|
filename: "[name].mjs",
|
|
247
255
|
chunkFilename: "[name].mjs",
|
|
248
256
|
assetModuleFilename: "res/[name][ext][query]",
|
|
249
|
-
|
|
257
|
+
library: {
|
|
258
|
+
type: "module"
|
|
259
|
+
}
|
|
250
260
|
},
|
|
251
261
|
watch: false,
|
|
252
262
|
watchOptions: { poll: undefined, ignored: undefined },
|
|
@@ -281,7 +291,7 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
281
291
|
__dirname: true
|
|
282
292
|
},
|
|
283
293
|
optimization: {
|
|
284
|
-
minimizer: watch ? [
|
|
294
|
+
minimizer: watch ? [] : [
|
|
285
295
|
new TerserPlugin({
|
|
286
296
|
extractComments: false,
|
|
287
297
|
terserOptions: {
|
|
@@ -298,7 +308,7 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
298
308
|
}
|
|
299
309
|
}
|
|
300
310
|
})
|
|
301
|
-
]
|
|
311
|
+
],
|
|
302
312
|
moduleIds: "deterministic",
|
|
303
313
|
chunkIds: watch ? "named" : "deterministic",
|
|
304
314
|
emitOnErrors: watch
|
|
@@ -314,12 +324,15 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
314
324
|
},
|
|
315
325
|
...watch ? [
|
|
316
326
|
{
|
|
317
|
-
test: /\.
|
|
327
|
+
test: /\.[cm]?jsx?$/,
|
|
318
328
|
enforce: "pre" as const,
|
|
319
329
|
loader: "source-map-loader",
|
|
320
330
|
options: {
|
|
321
331
|
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
322
|
-
|
|
332
|
+
const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
|
|
333
|
+
return !resourcePath.includes("node_modules")
|
|
334
|
+
|| (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
|
|
335
|
+
|| workspaceRegex.test(resourcePath);
|
|
323
336
|
}
|
|
324
337
|
}
|
|
325
338
|
}
|
|
@@ -418,9 +431,9 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
418
431
|
};
|
|
419
432
|
}
|
|
420
433
|
|
|
421
|
-
private
|
|
434
|
+
private _getExternalModules(): { name: string; exists: boolean }[] {
|
|
422
435
|
const loadedModuleNames: string[] = [];
|
|
423
|
-
const
|
|
436
|
+
const results: { name: string; exists: boolean }[] = [];
|
|
424
437
|
|
|
425
438
|
const fn = (currPath: string): void => {
|
|
426
439
|
const npmConfig = this._getNpmConfig(currPath);
|
|
@@ -438,7 +451,7 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
438
451
|
}
|
|
439
452
|
|
|
440
453
|
if (FsUtil.exists(path.resolve(modulePath, "binding.gyp"))) {
|
|
441
|
-
|
|
454
|
+
results.push({ name: moduleName, exists: true });
|
|
442
455
|
}
|
|
443
456
|
|
|
444
457
|
fn(modulePath);
|
|
@@ -450,12 +463,12 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
450
463
|
|
|
451
464
|
const optModulePath = FsUtil.findAllParentChildDirPaths("node_modules/" + optModuleName, currPath, this._workspaceRootPath).first();
|
|
452
465
|
if (StringUtil.isNullOrEmpty(optModulePath)) {
|
|
453
|
-
|
|
466
|
+
results.push({ name: optModuleName, exists: false });
|
|
454
467
|
continue;
|
|
455
468
|
}
|
|
456
469
|
|
|
457
470
|
if (FsUtil.exists(path.resolve(optModulePath, "binding.gyp"))) {
|
|
458
|
-
|
|
471
|
+
results.push({ name: optModuleName, exists: true });
|
|
459
472
|
}
|
|
460
473
|
|
|
461
474
|
fn(optModulePath);
|
|
@@ -464,7 +477,7 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
464
477
|
|
|
465
478
|
fn(this._rootPath);
|
|
466
479
|
|
|
467
|
-
return
|
|
480
|
+
return results;
|
|
468
481
|
}
|
|
469
482
|
|
|
470
483
|
private _getNpmConfig(pkgPath: string): INpmConfig | undefined {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { INpmConfig, ISdCliPackageBuildResult } from "../commons";
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
-
import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core
|
|
5
|
-
import
|
|
4
|
+
import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core-node";
|
|
5
|
+
import path from "path";
|
|
6
6
|
import { createHash } from "crypto";
|
|
7
7
|
import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
|
|
8
8
|
import { NgtscProgram } from "@angular/compiler-cli";
|
package/src/commons.ts
CHANGED
|
@@ -2,10 +2,8 @@ export interface INpmConfig {
|
|
|
2
2
|
name: string;
|
|
3
3
|
version: string;
|
|
4
4
|
workspaces?: string[];
|
|
5
|
-
es2020?: string;
|
|
6
|
-
browser?: string;
|
|
7
|
-
module?: string;
|
|
8
5
|
main?: string;
|
|
6
|
+
types?: string;
|
|
9
7
|
exports?: Record<string, {
|
|
10
8
|
types?: string;
|
|
11
9
|
}>;
|
|
@@ -23,7 +21,10 @@ export interface ITsconfig {
|
|
|
23
21
|
outDir?: string;
|
|
24
22
|
baseUrl?: string;
|
|
25
23
|
paths?: Record<string, string[]>;
|
|
24
|
+
declaration?: boolean;
|
|
26
25
|
};
|
|
26
|
+
files?: string[];
|
|
27
|
+
angularCompilerOptions?: Record<string, any>;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export interface ISdCliPackageBuildResult {
|
|
@@ -44,6 +45,9 @@ export type TSdCliPackageConfig = ISdCliLibPackageConfig | ISdCliServerPackageCo
|
|
|
44
45
|
|
|
45
46
|
export interface ISdCliLibPackageConfig {
|
|
46
47
|
type: "library";
|
|
48
|
+
autoIndex?: {
|
|
49
|
+
polyfills?: string[];
|
|
50
|
+
};
|
|
47
51
|
publish?: "npm";
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -59,4 +63,5 @@ export interface ISdCliClientPackageConfig {
|
|
|
59
63
|
type: "client";
|
|
60
64
|
server: string;
|
|
61
65
|
env?: Record<string, string>;
|
|
66
|
+
configs?: Record<string, any>;
|
|
62
67
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ITsconfig } from "../commons";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import chokidar from "chokidar";
|
|
6
|
+
|
|
7
|
+
export class SdCliIndexFileGenerator {
|
|
8
|
+
private readonly _indexFilePath = path.resolve(this.rootPath, "src/index.ts");
|
|
9
|
+
private _contentCache: string | undefined;
|
|
10
|
+
|
|
11
|
+
public constructor(public readonly rootPath: string,
|
|
12
|
+
public readonly config: ISdAutoIndexConfig) {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async watchAsync(): Promise<void> {
|
|
16
|
+
const watcher = chokidar.watch([path.resolve(this.rootPath, "src")], { persistent: true });
|
|
17
|
+
watcher.on("add", async (filePath) => {
|
|
18
|
+
if (filePath.endsWith(".ts")) {
|
|
19
|
+
await this.runAsync();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
watcher.on("unlink", async (filePath) => {
|
|
23
|
+
if (filePath.endsWith(".ts")) {
|
|
24
|
+
await this.runAsync();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
await this.runAsync();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async runAsync(): Promise<void> {
|
|
32
|
+
const importTexts: string[] = [];
|
|
33
|
+
|
|
34
|
+
// 옵션의 polyfills 를 모두 import
|
|
35
|
+
if (this.config.polyfills) {
|
|
36
|
+
for (const polyfill of this.config.polyfills) {
|
|
37
|
+
importTexts.push(`import "${polyfill}";`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 내부 파일들 import
|
|
42
|
+
const filePaths = await this._getFilePathsAsync();
|
|
43
|
+
for (const filePath of filePaths) {
|
|
44
|
+
const requirePath = PathUtil.posix(path.relative(path.dirname(this._indexFilePath), filePath))
|
|
45
|
+
.replace(/\.ts$/, "")
|
|
46
|
+
.replace(/\/index$/, "");
|
|
47
|
+
|
|
48
|
+
const sourceTsFileContent = await FsUtil.readFileAsync(filePath);
|
|
49
|
+
if (sourceTsFileContent.split("\n").some((line) => line.startsWith("export "))) {
|
|
50
|
+
importTexts.push(`export * from "./${requirePath}";`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
importTexts.push(`import "./${requirePath}";`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const content = importTexts.join(os.EOL) + os.EOL;
|
|
58
|
+
const prevContent = this._contentCache ?? (FsUtil.exists(this._indexFilePath) ? FsUtil.readFile(this._indexFilePath) : undefined);
|
|
59
|
+
this._contentCache = content;
|
|
60
|
+
if (content !== prevContent) {
|
|
61
|
+
await FsUtil.writeFileAsync(this._indexFilePath, content);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private async _getFilePathsAsync(): Promise<string[]> {
|
|
66
|
+
const tsconfig: ITsconfig = await FsUtil.readJsonAsync(path.resolve(this.rootPath, "tsconfig.json"));
|
|
67
|
+
const entryFilePaths = tsconfig.files?.map((item) => path.resolve(this.rootPath, item)) ?? [];
|
|
68
|
+
|
|
69
|
+
return (await FsUtil.globAsync(path.resolve(this.rootPath, "src/**/*.ts"), { nodir: true }))
|
|
70
|
+
.filter((item) => (
|
|
71
|
+
!entryFilePaths.includes(item)
|
|
72
|
+
&& item !== this._indexFilePath
|
|
73
|
+
));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface ISdAutoIndexConfig {
|
|
78
|
+
polyfills?: string[];
|
|
79
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SdCliConfigUtil } from "../utils/SdCliConfigUtil";
|
|
2
|
-
import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core
|
|
3
|
-
import
|
|
2
|
+
import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core-node";
|
|
3
|
+
import path from "path";
|
|
4
4
|
|
|
5
5
|
export class SdCliLocalUpdate {
|
|
6
6
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
@@ -14,6 +14,7 @@ export class SdCliLocalUpdate {
|
|
|
14
14
|
if (!conf.localUpdates) return;
|
|
15
15
|
|
|
16
16
|
const updatePathInfos = await this._getUpdatePathInfosAsync(conf.localUpdates);
|
|
17
|
+
this._logger.debug("로컬 업데이트 구성", updatePathInfos);
|
|
17
18
|
|
|
18
19
|
this._logger.log("로컬 라이브러리 업데이트 시작...");
|
|
19
20
|
for (const updatePathInfo of updatePathInfos) {
|
|
@@ -36,6 +37,7 @@ export class SdCliLocalUpdate {
|
|
|
36
37
|
if (!conf.localUpdates) return;
|
|
37
38
|
|
|
38
39
|
const updatePathInfos = await this._getUpdatePathInfosAsync(conf.localUpdates);
|
|
40
|
+
this._logger.debug("로컬 업데이트 구성", updatePathInfos);
|
|
39
41
|
|
|
40
42
|
const watchPaths = (await updatePathInfos.mapManyAsync(async (item) => await this._getWatchPathsAsync(item.source))).distinct();
|
|
41
43
|
|
|
@@ -73,7 +75,10 @@ export class SdCliLocalUpdate {
|
|
|
73
75
|
const result: IUpdatePathInfo[] = [];
|
|
74
76
|
for (const pkgGlobPath of Object.keys(record)) {
|
|
75
77
|
// "node_modules'에서 로컬업데이트 설정에 맞는 패키지를 "glob"하여 대상 패키지경로 목록 가져오기
|
|
76
|
-
const targetPaths =
|
|
78
|
+
const targetPaths = [
|
|
79
|
+
...await FsUtil.globAsync(path.resolve(this._rootPath, "node_modules", pkgGlobPath)),
|
|
80
|
+
...await FsUtil.globAsync(path.resolve(this._rootPath, "packages", "*", "node_modules", pkgGlobPath))
|
|
81
|
+
];
|
|
77
82
|
|
|
78
83
|
result.push(
|
|
79
84
|
...targetPaths
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core
|
|
1
|
+
import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { INpmConfig, ISdCliConfig, ISdCliPackageBuildResult } from "../commons";
|
|
4
4
|
import { SdCliPackage } from "../packages/SdCliPackage";
|
|
5
|
-
import { Uuid, Wait } from "@simplysm/sd-core
|
|
5
|
+
import { Uuid, Wait } from "@simplysm/sd-core-common";
|
|
6
6
|
import os from "os";
|
|
7
7
|
import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
|
|
8
8
|
import semver from "semver/preload";
|
|
9
9
|
import { SdCliConfigUtil } from "../utils/SdCliConfigUtil";
|
|
10
|
-
import { SdServiceServer } from "@simplysm/sd-service
|
|
10
|
+
import { SdServiceServer } from "@simplysm/sd-service-server";
|
|
11
11
|
import { SdCliNpm } from "./SdCliNpm";
|
|
12
12
|
import { SdCliLocalUpdate } from "./SdCliLocalUpdate";
|
|
13
13
|
import { NextHandleFunction } from "connect";
|
|
14
|
+
import { SdCliIndexFileGenerator } from "./SdCliIndexFileGenerator";
|
|
14
15
|
|
|
15
16
|
export class SdCliWorkspace {
|
|
16
17
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
@@ -35,6 +36,13 @@ export class SdCliWorkspace {
|
|
|
35
36
|
this._logger.debug("패키지 목록 구성...");
|
|
36
37
|
const pkgs = await this._getPackagesAsync(config);
|
|
37
38
|
|
|
39
|
+
this._logger.debug("패키지 인덱스 생성기 실행...");
|
|
40
|
+
await pkgs.parallelAsync(async (pkg) => {
|
|
41
|
+
if (pkg.config.type === "library" && pkg.config.autoIndex) {
|
|
42
|
+
await new SdCliIndexFileGenerator(pkg.rootPath, pkg.config.autoIndex).watchAsync();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
38
46
|
this._logger.debug("패키지 이벤트 설정...");
|
|
39
47
|
let changeCount = 0;
|
|
40
48
|
const totalResultMap = new Map<string, ISdCliPackageBuildResult[]>();
|
|
@@ -85,17 +93,23 @@ export class SdCliWorkspace {
|
|
|
85
93
|
});
|
|
86
94
|
}
|
|
87
95
|
|
|
96
|
+
private _isServerRestarting = false;
|
|
97
|
+
|
|
88
98
|
private async _restartServerAsync(pkg: SdCliPackage): Promise<void> {
|
|
99
|
+
await Wait.until(() => !this._isServerRestarting);
|
|
100
|
+
|
|
101
|
+
this._isServerRestarting = true;
|
|
89
102
|
const entryFileRelPath = pkg.main;
|
|
90
103
|
if (entryFileRelPath === undefined) {
|
|
91
104
|
this._logger.error(`서버패키지(${pkg.name})의 'package.json'에서 'main'필드를 찾을 수 없습니다.`);
|
|
105
|
+
this._isServerRestarting = false;
|
|
92
106
|
return;
|
|
93
107
|
}
|
|
94
108
|
const entryFilePath = path.resolve(pkg.rootPath, entryFileRelPath);
|
|
95
109
|
|
|
96
110
|
this._logger.log(`서버(${pkg.name}) 재시작...`);
|
|
97
111
|
try {
|
|
98
|
-
const serverInfo = this._serverInfoMap.getOrCreate(pkg.
|
|
112
|
+
const serverInfo = this._serverInfoMap.getOrCreate(path.basename(pkg.rootPath), { middlewares: [], clientInfos: [] });
|
|
99
113
|
if (serverInfo.server) {
|
|
100
114
|
await serverInfo.server.closeAsync();
|
|
101
115
|
delete serverInfo.server;
|
|
@@ -104,6 +118,7 @@ export class SdCliWorkspace {
|
|
|
104
118
|
serverInfo.server = (await import("file:///" + entryFilePath + "?update=" + Uuid.new().toString())).default as SdServiceServer | undefined;
|
|
105
119
|
if (!serverInfo.server) {
|
|
106
120
|
this._logger.error(`${entryFilePath}(0, 0): 'SdServiceServer'를 'export'해야 합니다.`);
|
|
121
|
+
this._isServerRestarting = false;
|
|
107
122
|
return;
|
|
108
123
|
}
|
|
109
124
|
serverInfo.server.devMiddlewares = serverInfo.middlewares;
|
|
@@ -114,6 +129,8 @@ export class SdCliWorkspace {
|
|
|
114
129
|
catch (err) {
|
|
115
130
|
this._logger.error(`서버(${pkg.name}) 재시작중 오류 발생`, err);
|
|
116
131
|
}
|
|
132
|
+
|
|
133
|
+
this._isServerRestarting = false;
|
|
117
134
|
}
|
|
118
135
|
|
|
119
136
|
public async buildAsync(opt: { confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
@@ -123,6 +140,13 @@ export class SdCliWorkspace {
|
|
|
123
140
|
this._logger.debug("패키지 목록 구성...");
|
|
124
141
|
const pkgs = await this._getPackagesAsync(config);
|
|
125
142
|
|
|
143
|
+
this._logger.debug("패키지 인덱스 생성기 실행...");
|
|
144
|
+
await pkgs.parallelAsync(async (pkg) => {
|
|
145
|
+
if (pkg.config.type === "library" && pkg.config.autoIndex) {
|
|
146
|
+
await new SdCliIndexFileGenerator(pkg.rootPath, pkg.config.autoIndex).runAsync();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
126
150
|
this._logger.debug("프로젝트 및 패키지 버전 설정...");
|
|
127
151
|
await this._upgradeVersionAsync(pkgs);
|
|
128
152
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { INpmConfig, ISdCliPackageBuildResult, ITsconfig, TSdCliPackageConfig } from "../commons";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { FsUtil, SdProcess } from "@simplysm/sd-core
|
|
3
|
+
import { FsUtil, SdProcess } from "@simplysm/sd-core-node";
|
|
4
4
|
import { EventEmitter } from "events";
|
|
5
|
-
import { ObjectUtil } from "@simplysm/sd-core
|
|
5
|
+
import { ObjectUtil } from "@simplysm/sd-core-common";
|
|
6
6
|
import { SdCliTsLibBuilder } from "../builder/SdCliTsLibBuilder";
|
|
7
7
|
import { SdCliJsLibBuilder } from "../builder/SdCliJsLibBuilder";
|
|
8
8
|
import { SdCliServerBuilder } from "../builder/SdCliServerBuilder";
|
|
@@ -116,6 +116,8 @@ export class SdCliPackage extends EventEmitter {
|
|
|
116
116
|
delete buildTsconfig.compilerOptions.baseUrl;
|
|
117
117
|
delete buildTsconfig.compilerOptions.paths;
|
|
118
118
|
|
|
119
|
+
buildTsconfig.compilerOptions.declaration = Boolean(this._npmConfig.types);
|
|
120
|
+
|
|
119
121
|
const buildTsconfigFilePath = path.resolve(this.rootPath, "tsconfig-build.json");
|
|
120
122
|
await FsUtil.writeJsonAsync(buildTsconfigFilePath, buildTsconfig, { space: 2 });
|
|
121
123
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ISdCliConfig, TSdCliPackageConfig } from "../commons";
|
|
2
|
-
import { FsUtil } from "@simplysm/sd-core
|
|
3
|
-
import { ObjectUtil } from "@simplysm/sd-core
|
|
2
|
+
import { FsUtil } from "@simplysm/sd-core-node";
|
|
3
|
+
import { ObjectUtil } from "@simplysm/sd-core-common";
|
|
4
4
|
import path from "path";
|
|
5
5
|
|
|
6
6
|
export class SdCliConfigUtil {
|
package/tsconfig-build.json
CHANGED
package/tsconfig.json
CHANGED
|
@@ -7,11 +7,17 @@
|
|
|
7
7
|
"outDir": "./dist",
|
|
8
8
|
"baseUrl": ".",
|
|
9
9
|
"paths": {
|
|
10
|
-
"@simplysm/sd-core
|
|
11
|
-
"../sd-core/src
|
|
10
|
+
"@simplysm/sd-core-common": [
|
|
11
|
+
"../sd-core-common/src/index.ts"
|
|
12
12
|
],
|
|
13
|
-
"@simplysm/sd-
|
|
14
|
-
"../sd-
|
|
13
|
+
"@simplysm/sd-core-node": [
|
|
14
|
+
"../sd-core-node/src/index.ts"
|
|
15
|
+
],
|
|
16
|
+
"@simplysm/sd-service-common": [
|
|
17
|
+
"../sd-service-common/src/index.ts"
|
|
18
|
+
],
|
|
19
|
+
"@simplysm/sd-service-server": [
|
|
20
|
+
"../sd-service-server/src/index.ts"
|
|
15
21
|
]
|
|
16
22
|
}
|
|
17
23
|
}
|
package/dist/bin/sd-cli.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
export declare class SdCliCacheCompilerHost {
|
|
3
|
-
static create(parsedTsconfig: ts.ParsedCommandLine, moduleResolutionCache: ts.ModuleResolutionCache, sourceFileCache: Map<string, IFileCache>, outputFileCache: Map<string, string>): ts.CompilerHost;
|
|
4
|
-
}
|
|
5
|
-
interface IFileCache {
|
|
6
|
-
exists?: boolean;
|
|
7
|
-
sourceFile?: ts.SourceFile;
|
|
8
|
-
content?: string;
|
|
9
|
-
}
|
|
10
|
-
export {};
|