@simplysm/sd-cli 7.0.66 → 7.0.77
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 +3 -0
- package/dist/bin/sd-cli.mjs +62 -6
- package/dist/build-tool/SdCliCordova.d.ts +1 -1
- package/dist/build-tool/SdCliCordova.mjs +40 -27
- package/dist/build-tool/SdCliNgCacheCompilerHost.d.ts +1 -0
- package/dist/build-tool/SdCliNgCacheCompilerHost.mjs +11 -4
- package/dist/build-tool/SdCliPackageLinter.mjs +9 -5
- package/dist/builder/SdCliClientBuilder.d.ts +1 -0
- package/dist/builder/SdCliClientBuilder.mjs +45 -37
- package/dist/builder/SdCliJsLibBuilder.mjs +3 -3
- package/dist/builder/SdCliServerBuilder.d.ts +0 -1
- package/dist/builder/SdCliServerBuilder.mjs +39 -54
- package/dist/builder/SdCliTsLibBuilder.d.ts +1 -0
- package/dist/builder/SdCliTsLibBuilder.mjs +19 -7
- package/dist/commons.d.ts +18 -4
- package/dist/entry-points/SdCliFileCrypto.d.ts +7 -0
- package/dist/entry-points/SdCliFileCrypto.mjs +72 -0
- package/dist/entry-points/SdCliLocalUpdate.mjs +3 -3
- package/dist/entry-points/SdCliPrepare.mjs +3 -3
- package/dist/entry-points/SdCliWorkspace.d.ts +3 -0
- package/dist/entry-points/SdCliWorkspace.mjs +57 -37
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +2 -1
- package/dist/ng-tools/SdCliNgModuleGenerator.d.ts +2 -0
- package/dist/ng-tools/SdCliNgModuleGenerator.mjs +97 -18
- package/dist/ng-tools/babel/SdCliBbFileMetadata.d.ts +1 -1
- package/dist/ng-tools/babel/SdCliBbFileMetadata.mjs +4 -4
- package/dist/ng-tools/babel/TSdCliBbNgMetadata.mjs +6 -6
- package/dist/ng-tools/typescript/SdCliTsFileMetadata.mjs +2 -3
- package/dist/packages/SdCliPackage.mjs +52 -5
- package/dist/utils/SdCliBuildResultUtil.mjs +4 -1
- package/package.json +7 -9
- package/src/bin/sd-cli.ts +77 -6
- package/src/build-tool/SdCliCordova.ts +43 -26
- package/src/build-tool/SdCliNgCacheCompilerHost.ts +19 -11
- package/src/build-tool/SdCliPackageLinter.ts +8 -4
- package/src/builder/SdCliClientBuilder.ts +42 -32
- package/src/builder/SdCliJsLibBuilder.ts +2 -2
- package/src/builder/SdCliServerBuilder.ts +37 -51
- package/src/builder/SdCliTsLibBuilder.ts +22 -6
- package/src/commons.ts +21 -2
- package/src/entry-points/SdCliFileCrypto.ts +87 -0
- package/src/entry-points/SdCliLocalUpdate.ts +2 -2
- package/src/entry-points/SdCliPrepare.ts +2 -2
- package/src/entry-points/SdCliWorkspace.ts +59 -41
- package/src/index.ts +1 -0
- package/src/ng-tools/SdCliNgModuleGenerator.ts +119 -17
- package/src/ng-tools/babel/SdCliBbFileMetadata.ts +5 -5
- package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +5 -5
- package/src/ng-tools/typescript/SdCliTsFileMetadata.ts +1 -2
- package/src/packages/SdCliPackage.ts +55 -4
- package/src/utils/SdCliBuildResultUtil.ts +4 -0
- package/tsconfig.json +3 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
|
|
1
|
+
import { FsUtil, Logger, PathUtil, 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";
|
|
@@ -23,7 +23,7 @@ export class SdCliWorkspace {
|
|
|
23
23
|
this._npmConfig = FsUtil.readJson(npmConfigFilePath);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
public async watchAsync(opt: { confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
26
|
+
public async watchAsync(opt: { confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
|
|
27
27
|
this._logger.debug("프로젝트 설정 가져오기...");
|
|
28
28
|
const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), true, opt.optNames);
|
|
29
29
|
|
|
@@ -33,7 +33,7 @@ export class SdCliWorkspace {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
this._logger.debug("패키지 목록 구성...");
|
|
36
|
-
const pkgs = await this._getPackagesAsync(config);
|
|
36
|
+
const pkgs = await this._getPackagesAsync(config, opt.pkgs);
|
|
37
37
|
|
|
38
38
|
this._logger.debug("패키지 이벤트 설정...");
|
|
39
39
|
let changeCount = 0;
|
|
@@ -72,22 +72,29 @@ export class SdCliWorkspace {
|
|
|
72
72
|
}
|
|
73
73
|
changeCount++;
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
await
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
try {
|
|
76
|
+
const pkgNames = pkgs.map((item) => item.name);
|
|
77
|
+
const buildCompletedPackageNames: string[] = [];
|
|
78
|
+
await pkgs.parallelAsync(async (pkg) => {
|
|
79
|
+
await Wait.until(() => !pkg.allDependencies.some((dep) => pkgNames.includes(dep) && !buildCompletedPackageNames.includes(dep)));
|
|
80
|
+
if (pkg.config.type === "client") {
|
|
81
|
+
const middlewares = (await pkg.watchAsync()) as NextHandleFunction[];
|
|
82
|
+
|
|
83
|
+
const serverInfo = this._serverInfoMap.getOrCreate(pkg.config.server, { middlewares: [], clientInfos: [] });
|
|
84
|
+
serverInfo.middlewares.push(...middlewares);
|
|
85
|
+
serverInfo.clientInfos.push({ pkgKey: pkg.name.split("/").last()! });
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
await pkg.watchAsync();
|
|
89
|
+
}
|
|
90
|
+
buildCompletedPackageNames.push(pkg.name);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
this._loggingResults(totalResultMap);
|
|
95
|
+
this._loggingOpenClientHrefs();
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
91
98
|
|
|
92
99
|
changeCount--;
|
|
93
100
|
if (changeCount === 0) {
|
|
@@ -111,18 +118,22 @@ export class SdCliWorkspace {
|
|
|
111
118
|
}
|
|
112
119
|
const entryFilePath = path.resolve(pkg.rootPath, entryFileRelPath);
|
|
113
120
|
|
|
114
|
-
this._logger.log(`서버(${pkg.name}) 재시작...`);
|
|
115
121
|
try {
|
|
116
122
|
const serverInfo = this._serverInfoMap.getOrCreate(path.basename(pkg.rootPath), {
|
|
117
123
|
middlewares: [],
|
|
118
124
|
clientInfos: []
|
|
119
125
|
});
|
|
120
126
|
if (serverInfo.server) {
|
|
127
|
+
this._logger.log(`[${pkg.name}] 기존 서버 중지...`);
|
|
121
128
|
await serverInfo.server.closeAsync();
|
|
122
129
|
delete serverInfo.server;
|
|
123
130
|
}
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
this._logger.log(`[${pkg.name}] 서버 시작중...`);
|
|
133
|
+
|
|
134
|
+
const serverMainPath = "file:///" + PathUtil.posix(entryFilePath) + "?update=" + Uuid.new().toString().replace(/-/g, "");
|
|
135
|
+
const serverModule = await import(serverMainPath);
|
|
136
|
+
serverInfo.server = serverModule.default as SdServiceServer | undefined;
|
|
126
137
|
if (!serverInfo.server) {
|
|
127
138
|
this._logger.error(`${entryFilePath}(0, 0): 'SdServiceServer'를 'export'해야 합니다.`);
|
|
128
139
|
this._isServerRestarting = false;
|
|
@@ -131,7 +142,7 @@ export class SdCliWorkspace {
|
|
|
131
142
|
serverInfo.server.devMiddlewares = serverInfo.middlewares;
|
|
132
143
|
await Wait.until(() => serverInfo.server!.isOpen);
|
|
133
144
|
|
|
134
|
-
this._logger.log(
|
|
145
|
+
this._logger.log(`[${pkg.name}] 서버가 시작되었습니다.`);
|
|
135
146
|
}
|
|
136
147
|
catch (err) {
|
|
137
148
|
this._logger.error(`서버(${pkg.name}) 재시작중 오류 발생`, err);
|
|
@@ -140,12 +151,12 @@ export class SdCliWorkspace {
|
|
|
140
151
|
this._isServerRestarting = false;
|
|
141
152
|
}
|
|
142
153
|
|
|
143
|
-
public async buildAsync(opt: { confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
154
|
+
public async buildAsync(opt: { confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
|
|
144
155
|
this._logger.debug("프로젝트 설정 가져오기...");
|
|
145
156
|
const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
|
|
146
157
|
|
|
147
158
|
this._logger.debug("패키지 목록 구성...");
|
|
148
|
-
const pkgs = await this._getPackagesAsync(config);
|
|
159
|
+
const pkgs = await this._getPackagesAsync(config, opt.pkgs);
|
|
149
160
|
|
|
150
161
|
this._logger.debug("프로젝트 및 패키지 버전 설정...");
|
|
151
162
|
await this._upgradeVersionAsync(pkgs);
|
|
@@ -159,26 +170,32 @@ export class SdCliWorkspace {
|
|
|
159
170
|
const pkgNames = pkgs.map((item) => item.name);
|
|
160
171
|
const buildCompletedPackageNames: string[] = [];
|
|
161
172
|
const totalResultMap = new Map<string, ISdCliPackageBuildResult[]>();
|
|
162
|
-
|
|
163
|
-
await
|
|
173
|
+
try {
|
|
174
|
+
await pkgs.parallelAsync(async (pkg) => {
|
|
175
|
+
await Wait.until(() => !pkg.allDependencies.some((dep) => pkgNames.includes(dep) && !buildCompletedPackageNames.includes(dep)));
|
|
164
176
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
this._logger.debug(`[${pkg.name}] 빌드를 시작합니다...`);
|
|
178
|
+
totalResultMap.set(pkg.name, await pkg.buildAsync());
|
|
179
|
+
this._logger.debug(`[${pkg.name}] 빌드가 완료되었습니다.`);
|
|
168
180
|
|
|
169
|
-
|
|
170
|
-
|
|
181
|
+
buildCompletedPackageNames.push(pkg.name);
|
|
182
|
+
});
|
|
171
183
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
184
|
+
this._loggingResults(totalResultMap);
|
|
185
|
+
if (Array.from(totalResultMap.values()).mapMany().some((item) => item.severity === "error")) {
|
|
186
|
+
throw new Error("빌드중 오류가 발생하였습니다.");
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
this._logger.info("모든 빌드가 완료되었습니다.");
|
|
190
|
+
}
|
|
175
191
|
}
|
|
176
|
-
|
|
177
|
-
this.
|
|
192
|
+
catch (err) {
|
|
193
|
+
this._loggingResults(totalResultMap);
|
|
194
|
+
throw err;
|
|
178
195
|
}
|
|
179
196
|
}
|
|
180
197
|
|
|
181
|
-
public async publishAsync(opt: { noBuild: boolean; confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
198
|
+
public async publishAsync(opt: { noBuild: boolean; confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
|
|
182
199
|
this._logger.debug("프로젝트 설정 가져오기...");
|
|
183
200
|
const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
|
|
184
201
|
|
|
@@ -197,7 +214,7 @@ export class SdCliWorkspace {
|
|
|
197
214
|
}
|
|
198
215
|
|
|
199
216
|
this._logger.debug("패키지 목록 구성...");
|
|
200
|
-
const pkgs = await this._getPackagesAsync(config);
|
|
217
|
+
const pkgs = await this._getPackagesAsync(config, opt.pkgs);
|
|
201
218
|
|
|
202
219
|
this._logger.debug("프로젝트 및 패키지 버전 설정...");
|
|
203
220
|
await this._upgradeVersionAsync(pkgs);
|
|
@@ -270,16 +287,17 @@ export class SdCliWorkspace {
|
|
|
270
287
|
process.stdout.clearLine(0);
|
|
271
288
|
}
|
|
272
289
|
|
|
273
|
-
private async _getPackagesAsync(conf: ISdCliConfig): Promise<SdCliPackage[]> {
|
|
290
|
+
private async _getPackagesAsync(conf: ISdCliConfig, pkgs: string[]): Promise<SdCliPackage[]> {
|
|
274
291
|
const pkgRootPaths = await this._npmConfig.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
|
|
275
292
|
if (!pkgRootPaths) {
|
|
276
293
|
throw new Error("최상위 'package.json'에서 'workspaces'를 찾을 수 없습니다.");
|
|
277
294
|
}
|
|
278
295
|
|
|
279
|
-
|
|
280
296
|
return pkgRootPaths.map((pkgRootPath) => {
|
|
297
|
+
if (pkgs.length > 0 && !pkgs.includes(path.basename(pkgRootPath))) return undefined;
|
|
281
298
|
const pkgConfig = conf.packages[path.basename(pkgRootPath)];
|
|
282
|
-
|
|
299
|
+
if (!pkgConfig) return undefined;
|
|
300
|
+
return new SdCliPackage(this._rootPath, pkgRootPath, pkgConfig);
|
|
283
301
|
}).filterExists();
|
|
284
302
|
}
|
|
285
303
|
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./builder/SdCliJsLibBuilder";
|
|
|
8
8
|
export * from "./builder/SdCliServerBuilder";
|
|
9
9
|
export * from "./builder/SdCliTsLibBuilder";
|
|
10
10
|
export * from "./commons";
|
|
11
|
+
export * from "./entry-points/SdCliFileCrypto";
|
|
11
12
|
export * from "./entry-points/SdCliLocalUpdate";
|
|
12
13
|
export * from "./entry-points/SdCliNpm";
|
|
13
14
|
export * from "./entry-points/SdCliPrepare";
|
|
@@ -7,17 +7,18 @@ import {
|
|
|
7
7
|
SdCliBbNgModuleMetadata,
|
|
8
8
|
SdCliBbNgPipeMetadata
|
|
9
9
|
} from "./babel/TSdCliBbNgMetadata";
|
|
10
|
-
import { NeverEntryError, StringUtil } from "@simplysm/sd-core-common";
|
|
10
|
+
import { NeverEntryError, ObjectUtil, StringUtil } from "@simplysm/sd-core-common";
|
|
11
11
|
import { TSdCliMetaRef } from "./commons";
|
|
12
12
|
import { SdCliTsNgInjectableMetadata } from "./typescript/SdCliTsFileMetadata";
|
|
13
13
|
import path from "path";
|
|
14
14
|
import { JSDOM } from "jsdom";
|
|
15
|
-
import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
|
|
15
|
+
import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core-node";
|
|
16
16
|
import os from "os";
|
|
17
|
+
import { INpmConfig } from "../commons";
|
|
17
18
|
|
|
18
|
-
// TODO: 에러 메시지 처리
|
|
19
|
-
// TODO: forRoot에 있는 Provider 처리??
|
|
20
19
|
export class SdCliNgModuleGenerator {
|
|
20
|
+
private readonly _logger: Logger;
|
|
21
|
+
|
|
21
22
|
private readonly _bbMeta: SdCliBbRootMetadata;
|
|
22
23
|
private readonly _tsMeta: SdCliTsRootMetadata;
|
|
23
24
|
|
|
@@ -44,6 +45,9 @@ export class SdCliNgModuleGenerator {
|
|
|
44
45
|
const content = FsUtil.readFile(currFilePath);
|
|
45
46
|
this._fileWriterCache.set(currFilePath, content);
|
|
46
47
|
}
|
|
48
|
+
|
|
49
|
+
const npmConfig: INpmConfig = FsUtil.readJson(path.resolve(packagePath, "package.json"));
|
|
50
|
+
this._logger = Logger.get(["simplysm", "sd-cli", this.constructor.name, npmConfig.name]);
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
public removeCaches(changedFilePaths: string[]): void {
|
|
@@ -57,20 +61,118 @@ export class SdCliNgModuleGenerator {
|
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
public async runAsync(): Promise<void> {
|
|
64
|
+
this._logger.debug("Babel NgModule 정의 가져오기...");
|
|
60
65
|
const bbNgModules = this._getBbNgModuleDefs();
|
|
66
|
+
|
|
67
|
+
this._logger.debug("NgModule Preset 구성...");
|
|
61
68
|
const tsPreset = this._getTsGenNgModulePreset();
|
|
62
69
|
|
|
70
|
+
this._logger.debug("RoutingModule 정의 구성...");
|
|
63
71
|
const genNgRoutingModules = await this._getGenNgRoutingModuleDefsAsync();
|
|
72
|
+
|
|
73
|
+
this._logger.debug("NgModule 정의 구성...");
|
|
64
74
|
const genNgModules = this._getGenNgModuleDefs(bbNgModules, tsPreset.modules, tsPreset.sources);
|
|
65
75
|
|
|
76
|
+
this._logger.debug("NgModule 순환참조 병합...");
|
|
77
|
+
const mergedGenNgModules = this._mergeNgModuleCircularDependency(genNgModules);
|
|
78
|
+
|
|
79
|
+
this._logger.debug("생성할 파일 내용 구성...");
|
|
66
80
|
const files = [
|
|
67
81
|
...this._getGenNgRoutingModuleFiles(genNgRoutingModules),
|
|
68
|
-
...this._getGenNgModuleFiles(
|
|
82
|
+
...this._getGenNgModuleFiles(mergedGenNgModules)
|
|
69
83
|
];
|
|
70
84
|
|
|
85
|
+
this._logger.debug("파일 쓰기...");
|
|
71
86
|
await this._writeFilesAsync(files);
|
|
72
87
|
}
|
|
73
88
|
|
|
89
|
+
private _mergeNgModuleCircularDependency(mods: ITsGenNgModuleDef[]): ITsGenNgModuleDef[] {
|
|
90
|
+
// 중복 'check'목록 구성
|
|
91
|
+
const check = (mod: ITsGenNgModuleDef, ref: { filePath: string; name: string }, chain: ITsGenNgModuleDef[]): ITsGenNgModuleDef[][] => {
|
|
92
|
+
const result: ITsGenNgModuleDef[][] = [];
|
|
93
|
+
for (const imp of mod.imports) {
|
|
94
|
+
if ("filePath" in imp) {
|
|
95
|
+
if (imp.filePath === ref.filePath || imp.name === ref.name) {
|
|
96
|
+
result.push(chain.concat([mod]));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const childMod = mods.single((item) => item.filePath === imp.filePath && item.name === imp.name);
|
|
100
|
+
if (childMod) {
|
|
101
|
+
if (chain.some((item) => item.filePath === childMod.filePath && item.name === childMod.name)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
result.push(
|
|
106
|
+
...check(childMod, ref, chain.concat([mod]))
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return result;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const checkedList: ITsGenNgModuleDef[][] = [];
|
|
117
|
+
for (const mod of mods) {
|
|
118
|
+
const circularDepModules = check(mod, { filePath: mod.filePath, name: mod.name }, []);
|
|
119
|
+
if (circularDepModules.length > 0) {
|
|
120
|
+
checkedList.push(...circularDepModules);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const mergeModPacks = checkedList.map((item) => item.orderBy((item1) => item1.filePath)).distinct();
|
|
124
|
+
|
|
125
|
+
// 'merge'목록 구성
|
|
126
|
+
const currMergedList: ITsGenNgModuleDef[] = [];
|
|
127
|
+
for (const mergeModPack of mergeModPacks) {
|
|
128
|
+
let currMerged = mergeModPack[0];
|
|
129
|
+
for (const mergeMod of mergeModPack.slice(1)) {
|
|
130
|
+
currMerged = {
|
|
131
|
+
filePath: currMerged.filePath,
|
|
132
|
+
name: currMerged.name,
|
|
133
|
+
imports: currMerged.imports.concat(mergeMod.imports).distinct(),
|
|
134
|
+
exports: currMerged.exports.concat(mergeMod.exports).distinct(),
|
|
135
|
+
providers: currMerged.providers.concat(mergeMod.providers).distinct()
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
currMerged.imports.remove((imp) => (
|
|
139
|
+
"filePath" in imp &&
|
|
140
|
+
mergeModPack.some((mergeMod) => (
|
|
141
|
+
imp.filePath === mergeMod.filePath &&
|
|
142
|
+
imp.name === mergeMod.name
|
|
143
|
+
))
|
|
144
|
+
));
|
|
145
|
+
|
|
146
|
+
currMergedList.push(currMerged);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 기존 'check'된 것들 모두 삭제
|
|
150
|
+
const result: ITsGenNgModuleDef[] = ObjectUtil.clone(mods);
|
|
151
|
+
for (const delMod of mergeModPacks.mapMany()) {
|
|
152
|
+
result.remove((item) => item.filePath === delMod.filePath && item.name === delMod.name);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 'merge'된 것들 등록
|
|
156
|
+
result.push(...currMergedList);
|
|
157
|
+
|
|
158
|
+
// 모든 결과물에서 'import'에 'merge'된것들이 있으면 'merge'결과물 파일로 변경후, distinct
|
|
159
|
+
for (const resultItem of result) {
|
|
160
|
+
for (const imp of resultItem.imports) {
|
|
161
|
+
if (!("filePath" in imp)) continue;
|
|
162
|
+
|
|
163
|
+
for (const mergeModPack of mergeModPacks) {
|
|
164
|
+
if (mergeModPack.some((mergeModPackItem) => mergeModPackItem.filePath === imp.filePath && mergeModPackItem.name === imp.name)) {
|
|
165
|
+
imp.filePath = mergeModPack[0].filePath;
|
|
166
|
+
imp.name = mergeModPack[0].name;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
resultItem.imports = resultItem.imports.distinct();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
|
|
74
176
|
private _findBbMetasFromMeta(srcMeta: TSdCliBbMetadata): TSdCliBbMetadata[] {
|
|
75
177
|
const metaTmp = typeof srcMeta !== "string" && "__TSdCliMetaRef__" in srcMeta ? this._bbMeta.findMeta(srcMeta) : srcMeta;
|
|
76
178
|
return metaTmp instanceof Array ? metaTmp : [metaTmp];
|
|
@@ -187,7 +289,7 @@ export class SdCliNgModuleGenerator {
|
|
|
187
289
|
const moduleFilePath = path.resolve(this._modulesPath, path.relative(this._srcPath, path.dirname(fileMeta.filePath)), moduleClassName);
|
|
188
290
|
|
|
189
291
|
result.sources.push({
|
|
190
|
-
filePath: fileMeta.filePath,
|
|
292
|
+
filePath: fileMeta.filePath.replace(/\.[^.]*$/, ""),
|
|
191
293
|
name: cls.exportedName,
|
|
192
294
|
module: {
|
|
193
295
|
filePath: moduleFilePath,
|
|
@@ -202,7 +304,7 @@ export class SdCliNgModuleGenerator {
|
|
|
202
304
|
filePath: moduleFilePath,
|
|
203
305
|
name: moduleClassName,
|
|
204
306
|
source: {
|
|
205
|
-
filePath: fileMeta.filePath,
|
|
307
|
+
filePath: fileMeta.filePath.replace(/\.[^.]*$/, ""),
|
|
206
308
|
name: cls.exportedName
|
|
207
309
|
},
|
|
208
310
|
selector: "selector" in cls.target.ngDecl ? cls.target.ngDecl.selector : undefined,
|
|
@@ -218,9 +320,9 @@ export class SdCliNgModuleGenerator {
|
|
|
218
320
|
private _getGenNgModuleDefs(bbModules: IBbNgModuleDef[], presetModules: ITsNgPresetModuleDef[], presetSources: ITsNgPresetSourceDef[]): ITsGenNgModuleDef[] {
|
|
219
321
|
const result: ITsGenNgModuleDef[] = [];
|
|
220
322
|
|
|
221
|
-
for (const
|
|
323
|
+
for (const presetSource of presetSources) {
|
|
222
324
|
const imports: TSdCliMetaRef[] = [];
|
|
223
|
-
for (const imp of
|
|
325
|
+
for (const imp of presetSource.imports) {
|
|
224
326
|
if ("moduleName" in imp) {
|
|
225
327
|
for (const mod of bbModules) {
|
|
226
328
|
if (mod.exports.some((item) => item.moduleName === imp.moduleName && item.name === imp.name)) {
|
|
@@ -240,8 +342,8 @@ export class SdCliNgModuleGenerator {
|
|
|
240
342
|
}
|
|
241
343
|
}
|
|
242
344
|
|
|
243
|
-
if (
|
|
244
|
-
const templateDOM = new JSDOM(
|
|
345
|
+
if (presetSource.template !== undefined) {
|
|
346
|
+
const templateDOM = new JSDOM(presetSource.template);
|
|
245
347
|
|
|
246
348
|
for (const mod of bbModules) {
|
|
247
349
|
for (const selector of mod.selectors) {
|
|
@@ -257,7 +359,7 @@ export class SdCliNgModuleGenerator {
|
|
|
257
359
|
}
|
|
258
360
|
|
|
259
361
|
for (const pipeName of mod.pipeNames) {
|
|
260
|
-
if (new RegExp("| *" + pipeName + "[^\\w]").test(
|
|
362
|
+
if (new RegExp("| *" + pipeName + "[^\\w]").test(presetSource.template)) {
|
|
261
363
|
imports.push({ moduleName: mod.moduleName, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
|
|
262
364
|
}
|
|
263
365
|
}
|
|
@@ -277,7 +379,7 @@ export class SdCliNgModuleGenerator {
|
|
|
277
379
|
}
|
|
278
380
|
|
|
279
381
|
if (mod.pipeName !== undefined) {
|
|
280
|
-
if (new RegExp("| *" + mod.pipeName + "[^\\w]").test(
|
|
382
|
+
if (new RegExp("| *" + mod.pipeName + "[^\\w]").test(presetSource.template)) {
|
|
281
383
|
imports.push({ filePath: mod.filePath, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
|
|
282
384
|
}
|
|
283
385
|
}
|
|
@@ -285,11 +387,11 @@ export class SdCliNgModuleGenerator {
|
|
|
285
387
|
}
|
|
286
388
|
|
|
287
389
|
result.push({
|
|
288
|
-
filePath:
|
|
289
|
-
name:
|
|
390
|
+
filePath: presetSource.module.filePath,
|
|
391
|
+
name: presetSource.module.name,
|
|
290
392
|
imports: imports.distinct(),
|
|
291
|
-
exports:
|
|
292
|
-
providers:
|
|
393
|
+
exports: presetSource.isProvider ? [] : [{ filePath: presetSource.filePath, name: presetSource.name }],
|
|
394
|
+
providers: presetSource.isProvider ? [{ filePath: presetSource.filePath, name: presetSource.name }] : []
|
|
293
395
|
});
|
|
294
396
|
}
|
|
295
397
|
|
|
@@ -441,9 +441,9 @@ export class SdCliBbFileMetadata {
|
|
|
441
441
|
throw SdCliBbUtil.error("예상치 못한 방식의 코드가 발견되었습니다.", this.filePath, rawMeta);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
-
private readonly _getNgDecoArgCache = new Map<string, SdCliBbObjectMetadata>();
|
|
444
|
+
private readonly _getNgDecoArgCache = new Map<string, SdCliBbObjectMetadata | undefined>();
|
|
445
445
|
|
|
446
|
-
public getNgDecoArg(className: string): SdCliBbObjectMetadata {
|
|
446
|
+
public getNgDecoArg(className: string): SdCliBbObjectMetadata | undefined {
|
|
447
447
|
if (this._getNgDecoArgCache.has(className)) {
|
|
448
448
|
return this._getNgDecoArgCache.get(className)!;
|
|
449
449
|
}
|
|
@@ -529,9 +529,9 @@ export class SdCliBbFileMetadata {
|
|
|
529
529
|
}
|
|
530
530
|
});
|
|
531
531
|
|
|
532
|
-
if (result === undefined) {
|
|
533
|
-
|
|
534
|
-
}
|
|
532
|
+
// if (result === undefined) {
|
|
533
|
+
// throw new NeverEntryError(this.filePath + "," + className);
|
|
534
|
+
// }
|
|
535
535
|
|
|
536
536
|
this._getNgDecoArgCache.set(className, result);
|
|
537
537
|
return result;
|
|
@@ -27,13 +27,13 @@ export class SdCliBbNgModuleMetadata {
|
|
|
27
27
|
|
|
28
28
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
29
29
|
|
|
30
|
-
const expVal = argObjMeta
|
|
30
|
+
const expVal = argObjMeta?.getPropValue("exports") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "exports");
|
|
31
31
|
if (expVal !== undefined) {
|
|
32
32
|
const expMetas = this._getExportAndProviderMetas(expVal);
|
|
33
33
|
result.exports.push(...expMetas);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const provVal = argObjMeta
|
|
36
|
+
const provVal = argObjMeta?.getPropValue("providers") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "providers");
|
|
37
37
|
if (provVal !== undefined) {
|
|
38
38
|
const provMetas = this._getExportAndProviderMetas(provVal);
|
|
39
39
|
result.providers.push(...provMetas);
|
|
@@ -140,7 +140,7 @@ export class SdCliBbNgDirectiveMetadata {
|
|
|
140
140
|
if (this._selectorCache !== undefined) return this._selectorCache;
|
|
141
141
|
|
|
142
142
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
143
|
-
const val = argObjMeta
|
|
143
|
+
const val = argObjMeta?.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵdir", "selector");
|
|
144
144
|
if (typeof val === "string") {
|
|
145
145
|
this._selectorCache = val;
|
|
146
146
|
return this._selectorCache;
|
|
@@ -162,7 +162,7 @@ export class SdCliBbNgComponentMetadata {
|
|
|
162
162
|
if (this._selectorCache !== undefined) return this._selectorCache;
|
|
163
163
|
|
|
164
164
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
165
|
-
const val = argObjMeta
|
|
165
|
+
const val = argObjMeta?.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵcmp", "selector");
|
|
166
166
|
if (typeof val === "string") {
|
|
167
167
|
this._selectorCache = val;
|
|
168
168
|
return this._selectorCache;
|
|
@@ -184,7 +184,7 @@ export class SdCliBbNgPipeMetadata {
|
|
|
184
184
|
if (this._pipeNameCache !== undefined) return this._pipeNameCache;
|
|
185
185
|
|
|
186
186
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
187
|
-
const val = argObjMeta
|
|
187
|
+
const val = argObjMeta?.getPropValue("name") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵpipe", "name");
|
|
188
188
|
if (typeof val === "string") {
|
|
189
189
|
this._pipeNameCache = val;
|
|
190
190
|
return val;
|
|
@@ -3,7 +3,6 @@ import ts from "typescript";
|
|
|
3
3
|
import { NeverEntryError } from "@simplysm/sd-core-common";
|
|
4
4
|
import { TSdCliMetaRef } from "../commons";
|
|
5
5
|
import path from "path";
|
|
6
|
-
import { SdCliTsUtil } from "./SdCliTsUtil";
|
|
7
6
|
|
|
8
7
|
export class SdCliTsFileMetadata {
|
|
9
8
|
public readonly sourceFile: ts.SourceFile;
|
|
@@ -53,7 +52,7 @@ export class SdCliTsFileMetadata {
|
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
else {
|
|
56
|
-
throw SdCliTsUtil.error("'import * as [name] from ...'을 'import [name] from ...'로 변경하세요.", this.sourceFile, node);
|
|
55
|
+
// throw SdCliTsUtil.error("'import * as [name] from ...'을 'import [name] from ...'로 변경하세요.", this.sourceFile, node);
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
else {
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { INpmConfig, ISdCliPackageBuildResult, ITsconfig, TSdCliPackageConfig } from "../commons";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { FsUtil, SdProcess } from "@simplysm/sd-core-node";
|
|
3
|
+
import { FsUtil, PathUtil, SdProcess } from "@simplysm/sd-core-node";
|
|
4
4
|
import { EventEmitter } from "events";
|
|
5
|
-
import { ObjectUtil } from "@simplysm/sd-core-common";
|
|
5
|
+
import { NeverEntryError, ObjectUtil, StringUtil } 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";
|
|
9
9
|
import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
|
|
10
10
|
import { SdCliClientBuilder } from "../builder/SdCliClientBuilder";
|
|
11
11
|
import { NextHandleFunction } from "connect";
|
|
12
|
+
import { SdStorage } from "@simplysm/sd-storage";
|
|
13
|
+
import ts from "typescript";
|
|
12
14
|
|
|
13
15
|
export class SdCliPackage extends EventEmitter {
|
|
14
16
|
private readonly _npmConfig: INpmConfig;
|
|
@@ -83,8 +85,57 @@ export class SdCliPackage extends EventEmitter {
|
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
public async publishAsync(): Promise<void> {
|
|
86
|
-
if (this.config.
|
|
87
|
-
|
|
88
|
+
if (this.config.publish !== undefined) {
|
|
89
|
+
if (this.config.type === "library") {
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
91
|
+
if (this.config.publish === "npm") {
|
|
92
|
+
await SdProcess.spawnAsync("npm publish --quiet --access public", { cwd: this.rootPath });
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
throw new NeverEntryError();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (this.config.publish.type === "ftp" || this.config.publish.type === "ftps" || this.config.publish.type === "sftp") {
|
|
100
|
+
const tsconfigPath = path.resolve(this.rootPath, "tsconfig-build.json");
|
|
101
|
+
const tsconfig = FsUtil.readJson(tsconfigPath);
|
|
102
|
+
const parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this.rootPath, tsconfig.angularCompilerOptions);
|
|
103
|
+
|
|
104
|
+
const ftp = await SdStorage.connectAsync(this.config.publish.type, {
|
|
105
|
+
host: this.config.publish.host,
|
|
106
|
+
port: this.config.publish.port,
|
|
107
|
+
user: this.config.publish.user,
|
|
108
|
+
pass: this.config.publish.pass
|
|
109
|
+
});
|
|
110
|
+
await ftp.uploadDirAsync(parsedTsconfig.options.outDir!, this.config.publish.path);
|
|
111
|
+
await ftp.closeAsync();
|
|
112
|
+
}
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
114
|
+
else if (this.config.publish.type === "local-directory") {
|
|
115
|
+
const tsconfigPath = path.resolve(this.rootPath, "tsconfig-build.json");
|
|
116
|
+
const tsconfig = FsUtil.readJson(tsconfigPath);
|
|
117
|
+
const parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this.rootPath, tsconfig.angularCompilerOptions);
|
|
118
|
+
|
|
119
|
+
const targetRootPath = this.config.publish.path.replace(/%([^%]*)%/g, (item) => {
|
|
120
|
+
const envName = item.replace(/%/g, "");
|
|
121
|
+
if (!StringUtil.isNullOrEmpty(this._npmConfig.version) && envName === "SD_VERSION") {
|
|
122
|
+
return this._npmConfig.version;
|
|
123
|
+
}
|
|
124
|
+
return process.env[envName] ?? item;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const filePaths = await FsUtil.globAsync(path.resolve(this.rootPath, "**", "*"), {
|
|
128
|
+
dot: true,
|
|
129
|
+
nodir: true
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
await filePaths.parallelAsync(async (filePath) => {
|
|
133
|
+
const relativeFilePath = path.relative(parsedTsconfig.options.outDir!, filePath);
|
|
134
|
+
const targetPath = PathUtil.posix(targetRootPath, relativeFilePath);
|
|
135
|
+
await FsUtil.copyAsync(filePath, targetPath);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
88
139
|
}
|
|
89
140
|
}
|
|
90
141
|
|
|
@@ -59,6 +59,10 @@ export class SdCliBuildResultUtil {
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
public static getMessage(result: ISdCliPackageBuildResult): string {
|
|
62
|
+
if (result.code === "ESLintError") {
|
|
63
|
+
return result.message;
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
let str = "";
|
|
63
67
|
if (result.filePath !== undefined) {
|
|
64
68
|
str += `${result.filePath}(${result.line ?? 0}, ${result.char ?? 0}): `;
|