@simplysm/sd-cli 6.0.26 → 6.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-node/bin/sd-cli.js +19 -4
- package/dist-node/bin/sd-cli.js.map +1 -1
- package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js +102 -49
- package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js.map +1 -1
- package/dist-node/build-tools/metadata/SdAotMetadataReader.js +6 -2
- package/dist-node/build-tools/metadata/SdAotMetadataReader.js.map +1 -1
- package/dist-node/build-tools/metadata/SdIvyMetadataReader.js +22 -5
- package/dist-node/build-tools/metadata/SdIvyMetadataReader.js.map +1 -1
- package/dist-node/build-tools/metadata/SdMetadataError.js +13 -0
- package/dist-node/build-tools/metadata/SdMetadataError.js.map +1 -0
- package/dist-node/build-tools/metadata/SdMyMetadataReader.js +22 -5
- package/dist-node/build-tools/metadata/SdMyMetadataReader.js.map +1 -1
- package/dist-node/builders/SdCliNgClientBuilder.js +73 -66
- package/dist-node/builders/SdCliNgClientBuilder.js.map +1 -1
- package/dist-node/builders/SdCliNgLibraryBuilder.js +52 -24
- package/dist-node/builders/SdCliNgLibraryBuilder.js.map +1 -1
- package/dist-node/builders/SdCliServerBuilder.js +45 -44
- package/dist-node/builders/SdCliServerBuilder.js.map +1 -1
- package/dist-node/builders/SdCliTypescriptBuilder.js +64 -59
- package/dist-node/builders/SdCliTypescriptBuilder.js.map +1 -1
- package/dist-node/entry-points/SdCliLocalUpdater.js +30 -29
- package/dist-node/entry-points/SdCliLocalUpdater.js.map +1 -1
- package/dist-node/entry-points/SdCliProject.js +10 -16
- package/dist-node/entry-points/SdCliProject.js.map +1 -1
- package/dist-node/packages/SdCliClientPackage.js +4 -3
- package/dist-node/packages/SdCliClientPackage.js.map +1 -1
- package/dist-node/packages/SdCliLibraryPackage.js +3 -2
- package/dist-node/packages/SdCliLibraryPackage.js.map +1 -1
- package/dist-node/packages/SdCliServerPackage.js +4 -3
- package/dist-node/packages/SdCliServerPackage.js.map +1 -1
- package/dist-node/utils/SdProjectConfigUtil.js +1 -1
- package/dist-node/utils/SdProjectConfigUtil.js.map +1 -1
- package/dist-node/utils/SdWebpackUtil.js +33 -13
- package/dist-node/utils/SdWebpackUtil.js.map +1 -1
- package/dist-node/workers/client-ng-gen-worker.js +54 -0
- package/dist-node/workers/client-ng-gen-worker.js.map +1 -0
- package/dist-node/workers/lib-build-worker.js +7 -6
- package/dist-node/workers/lib-build-worker.js.map +1 -1
- package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts +1 -0
- package/dist-types/build-tools/metadata/SdMetadataError.d.ts +6 -0
- package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts +1 -0
- package/dist-types/builders/SdCliNgClientBuilder.d.ts +6 -2
- package/dist-types/builders/SdCliNgLibraryBuilder.d.ts +3 -1
- package/dist-types/builders/SdCliServerBuilder.d.ts +2 -1
- package/dist-types/builders/SdCliTypescriptBuilder.d.ts +5 -5
- package/dist-types/commons.d.ts +3 -1
- package/dist-types/entry-points/SdCliLocalUpdater.d.ts +1 -1
- package/dist-types/entry-points/SdCliProject.d.ts +2 -0
- package/dist-types/packages/SdCliClientPackage.d.ts +2 -1
- package/dist-types/packages/SdCliLibraryPackage.d.ts +2 -1
- package/dist-types/packages/SdCliServerPackage.d.ts +2 -1
- package/dist-types/utils/SdWebpackUtil.d.ts +1 -1
- package/dist-types/workers/client-ng-gen-worker.d.ts +1 -0
- package/package.json +7 -7
- package/schema/schema.json +185 -122
- package/sd-tsconfig.node.json +2 -1
- package/src/bin/sd-cli.ts +19 -4
- package/src/build-tools/SdCliNgModuleFilesGenerator.ts +118 -60
- package/src/build-tools/metadata/SdAotMetadataReader.ts +8 -2
- package/src/build-tools/metadata/SdIvyMetadataReader.ts +27 -4
- package/src/build-tools/metadata/SdMetadataError.ts +7 -0
- package/src/build-tools/metadata/SdMyMetadataReader.ts +25 -3
- package/src/builders/SdCliNgClientBuilder.ts +122 -58
- package/src/builders/SdCliNgLibraryBuilder.ts +102 -43
- package/src/builders/SdCliServerBuilder.ts +61 -44
- package/src/builders/SdCliTypescriptBuilder.ts +92 -73
- package/src/commons.ts +1 -1
- package/src/entry-points/SdCliLocalUpdater.ts +40 -33
- package/src/entry-points/SdCliProject.ts +14 -13
- package/src/packages/SdCliClientPackage.ts +3 -2
- package/src/packages/SdCliLibraryPackage.ts +2 -1
- package/src/packages/SdCliServerPackage.ts +4 -3
- package/src/utils/SdCliFileCrypto.ts +1 -1
- package/src/utils/SdProjectConfigUtil.ts +1 -1
- package/src/utils/SdWebpackUtil.ts +42 -22
- package/src/workers/client-ng-gen-worker.ts +60 -0
- package/src/workers/lib-build-worker.ts +7 -6
- package/tsconfig.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ISdPackageBuildResult } from "../commons";
|
|
2
|
-
import { NeverEntryError, ObjectUtil, StringUtil } from "@simplysm/sd-core-common";
|
|
2
|
+
import { NeverEntryError, ObjectUtil, SdError, StringUtil } from "@simplysm/sd-core-common";
|
|
3
3
|
import * as ts from "typescript";
|
|
4
4
|
import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
|
|
5
5
|
import * as path from "path";
|
|
@@ -25,7 +25,9 @@ import {
|
|
|
25
25
|
} from "./metadata/SdAotMetadataReader";
|
|
26
26
|
import { IIvyNgModuleMetadata, SdIvyMetadataReader, TIvyNgMetadata } from "./metadata/SdIvyMetadataReader";
|
|
27
27
|
import { NgtscProgram } from "@angular/compiler-cli";
|
|
28
|
+
import { SdMetadataError } from "./metadata/SdMetadataError";
|
|
28
29
|
|
|
30
|
+
// TODO: LazyPage??
|
|
29
31
|
export class SdCliNgModuleFilesGenerator {
|
|
30
32
|
private readonly _fileCache = new Map<string, TFileCache>();
|
|
31
33
|
|
|
@@ -57,49 +59,81 @@ export class SdCliNgModuleFilesGenerator {
|
|
|
57
59
|
|
|
58
60
|
let changed = false;
|
|
59
61
|
for (const dirtyFilePath of dirtyFilePaths) {
|
|
60
|
-
|
|
62
|
+
try {
|
|
63
|
+
if (PathUtil.isChildPath(dirtyFilePath, this._moduleDistDirPath)) continue;
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
this._fileCache.delete(dirtyFilePath);
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
sourceFile,
|
|
72
|
-
metadata: new SdMyMetadataReader(sourceFile, this._program).getMetadatas()
|
|
73
|
-
});
|
|
74
|
-
changed = true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// AOT 라이브러리
|
|
78
|
-
else if (dirtyFilePath.endsWith(".d.ts")) {
|
|
79
|
-
const sourceFile = this._program.getSourceFile(dirtyFilePath);
|
|
80
|
-
if (!sourceFile) throw new NeverEntryError();
|
|
81
|
-
|
|
82
|
-
// from METADATA
|
|
83
|
-
const metadataFilePath = dirtyFilePath.replace(/\.d\.ts$/, ".metadata.json");
|
|
84
|
-
if (FsUtil.exists(metadataFilePath)) {
|
|
85
|
-
const metadataRoot = await FsUtil.readJsonAsync(metadataFilePath);
|
|
67
|
+
// 내 소스코드
|
|
68
|
+
if (dirtyFilePath.endsWith(".ts") && !dirtyFilePath.endsWith(".d.ts")) {
|
|
69
|
+
const sourceFile = this._program.getSourceFile(dirtyFilePath);
|
|
70
|
+
if (!sourceFile) { // 삭제된 파일
|
|
71
|
+
changed = true;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
86
74
|
|
|
87
75
|
this._fileCache.set(dirtyFilePath, {
|
|
88
|
-
type: "
|
|
76
|
+
type: "my",
|
|
89
77
|
sourceFile,
|
|
90
|
-
|
|
78
|
+
metadata: new SdMyMetadataReader(sourceFile, this._program).getMetadatas()
|
|
91
79
|
});
|
|
92
80
|
changed = true;
|
|
93
81
|
}
|
|
94
82
|
|
|
95
|
-
//
|
|
96
|
-
else {
|
|
97
|
-
this.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
83
|
+
// AOT 라이브러리
|
|
84
|
+
else if (dirtyFilePath.endsWith(".d.ts")) {
|
|
85
|
+
const sourceFile = this._program.getSourceFile(dirtyFilePath);
|
|
86
|
+
if (!sourceFile) { // 삭제된 파일
|
|
87
|
+
changed = true;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// from METADATA
|
|
92
|
+
const metadataFilePath = dirtyFilePath.replace(/\.d\.ts$/, ".metadata.json");
|
|
93
|
+
const sdMetadataFilePath = dirtyFilePath.replace(/\.d\.ts$/, ".sd-metadata.json");
|
|
94
|
+
|
|
95
|
+
if (FsUtil.exists(metadataFilePath)) {
|
|
96
|
+
const metadataRoot = await FsUtil.readJsonAsync(metadataFilePath);
|
|
97
|
+
|
|
98
|
+
this._fileCache.set(dirtyFilePath, {
|
|
99
|
+
type: "aot",
|
|
100
|
+
sourceFile,
|
|
101
|
+
...new SdAotMetadataReader(metadataRoot).getMetadatas()
|
|
102
|
+
});
|
|
103
|
+
changed = true;
|
|
104
|
+
}
|
|
105
|
+
else if (FsUtil.exists(sdMetadataFilePath)) {
|
|
106
|
+
const metadataRoot = await FsUtil.readJsonAsync(sdMetadataFilePath);
|
|
107
|
+
|
|
108
|
+
this._fileCache.set(dirtyFilePath, {
|
|
109
|
+
type: "aot",
|
|
110
|
+
sourceFile,
|
|
111
|
+
...new SdAotMetadataReader(metadataRoot).getMetadatas()
|
|
112
|
+
});
|
|
113
|
+
changed = true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// from IVY
|
|
117
|
+
else {
|
|
118
|
+
this._fileCache.set(dirtyFilePath, {
|
|
119
|
+
type: "ivy",
|
|
120
|
+
sourceFile,
|
|
121
|
+
...new SdIvyMetadataReader(sourceFile, ngProgram).getMetadatas()
|
|
122
|
+
});
|
|
123
|
+
changed = true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
if (err instanceof SdMetadataError) {
|
|
129
|
+
result.push({
|
|
130
|
+
filePath: err.fileName,
|
|
131
|
+
severity: "error",
|
|
132
|
+
message: err.message
|
|
101
133
|
});
|
|
102
|
-
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
throw new SdError(err, "'" + dirtyFilePath + "' 메타데이터 로딩중 에러");
|
|
103
137
|
}
|
|
104
138
|
}
|
|
105
139
|
}
|
|
@@ -108,29 +142,48 @@ export class SdCliNgModuleFilesGenerator {
|
|
|
108
142
|
}
|
|
109
143
|
|
|
110
144
|
public async generateAsync(): Promise<{ result: ISdPackageBuildResult[]; changedFilePaths: string[] }> {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
145
|
+
try {
|
|
146
|
+
let moduleInfoMap = this._getModuleInfoMap();
|
|
147
|
+
moduleInfoMap = this._mergeCircularModuleInfoMap(moduleInfoMap);
|
|
148
|
+
|
|
149
|
+
const routingModuleMap = await this._getRoutingModuleInfoMapAsync();
|
|
150
|
+
|
|
151
|
+
const changedFilePaths = [
|
|
152
|
+
...await this._writeNgModuleFileAsync(moduleInfoMap),
|
|
153
|
+
...await this._writeRoutingModuleFileAsync(moduleInfoMap, routingModuleMap)
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
const genFilePaths = [...moduleInfoMap.keys(), ...routingModuleMap.keys()].distinct();
|
|
157
|
+
const delFilePaths = (await FsUtil.globAsync(path.resolve(this._moduleDistDirPath, "**", "*")))
|
|
158
|
+
.filter((item) => (
|
|
159
|
+
!genFilePaths.includes(PathUtil.posix(item))
|
|
160
|
+
&& !genFilePaths.some((item1) => PathUtil.isChildPath(item1, item))
|
|
161
|
+
))
|
|
162
|
+
.map((item) => PathUtil.posix(item));
|
|
163
|
+
for (const delFilePath of delFilePaths) {
|
|
164
|
+
changedFilePaths.push(delFilePath);
|
|
165
|
+
await FsUtil.removeAsync(delFilePath);
|
|
166
|
+
}
|
|
132
167
|
|
|
133
|
-
|
|
168
|
+
return { result: [], changedFilePaths: changedFilePaths.distinct() };
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
if (err instanceof SdMetadataError) {
|
|
172
|
+
return {
|
|
173
|
+
result: [
|
|
174
|
+
{
|
|
175
|
+
filePath: err.fileName,
|
|
176
|
+
severity: "error",
|
|
177
|
+
message: err.message
|
|
178
|
+
}
|
|
179
|
+
],
|
|
180
|
+
changedFilePaths: []
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
throw new SdError(err, "메타데이터 생성중 에러");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
134
187
|
}
|
|
135
188
|
|
|
136
189
|
// region NgModule
|
|
@@ -500,7 +553,10 @@ export class ${moduleInfo.className} {
|
|
|
500
553
|
const expFilePath = this._getResolvedFilePath(filePath, moduleName);
|
|
501
554
|
if (StringUtil.isNullOrEmpty(expFilePath)) throw new NeverEntryError();
|
|
502
555
|
const expFileCache = this._fileCache.get(expFilePath);
|
|
503
|
-
if (!expFileCache
|
|
556
|
+
if (!expFileCache) {
|
|
557
|
+
throw new SdMetadataError(filePath, `파일 '${expFilePath}'을 찾을 수 없습니다.`);
|
|
558
|
+
}
|
|
559
|
+
if (expFileCache.type !== "aot") throw new NeverEntryError();
|
|
504
560
|
const newExp = expFileCache.exports.single((item) => (item.as ?? item.name) === targetName);
|
|
505
561
|
if (!newExp) throw new NeverEntryError();
|
|
506
562
|
|
|
@@ -600,7 +656,7 @@ export class ${moduleInfo.className} {
|
|
|
600
656
|
if (fileCache.type !== "my") continue;
|
|
601
657
|
|
|
602
658
|
for (const metadata of fileCache.metadata) {
|
|
603
|
-
if (
|
|
659
|
+
if (!metadata.className.endsWith("Page")) continue;
|
|
604
660
|
|
|
605
661
|
const newRoutingModuleInfo: IGenRoutingModuleInfo = {
|
|
606
662
|
path: "",
|
|
@@ -669,7 +725,6 @@ export class ${moduleInfo.className} {
|
|
|
669
725
|
const moduleImportTexts: string[] = [];
|
|
670
726
|
|
|
671
727
|
const pageFilePath = this._getModuleModuleImportName(path.dirname(distFilePath), routingModuleInfo.page.moduleFilePath);
|
|
672
|
-
moduleImportTexts.push(`import { ${routingModuleInfo.page.name} } from "${pageFilePath}";`);
|
|
673
728
|
|
|
674
729
|
let content: string;
|
|
675
730
|
if (path.basename(distFilePath) === "_routes.ts") {
|
|
@@ -685,6 +740,7 @@ export const routes: Routes = [
|
|
|
685
740
|
else {
|
|
686
741
|
moduleImportTexts.push(`import { NgModule } from "@angular/core";`);
|
|
687
742
|
moduleImportTexts.push(`import { RouterModule } from "@angular/router";`);
|
|
743
|
+
moduleImportTexts.push(`import { ${routingModuleInfo.page.name} } from "${pageFilePath}";`);
|
|
688
744
|
|
|
689
745
|
const thisPageModuleInfoEntry = Array.from(moduleInfoMap.entries())
|
|
690
746
|
.single((item) => item[1].exports.some((exp) => exp.moduleFilePath === routingModuleInfo.page.moduleFilePath && exp.name === routingModuleInfo.page.name));
|
|
@@ -733,7 +789,9 @@ export class ${routingModuleInfo.page.name}RoutingModule {
|
|
|
733
789
|
private _getRoutingModuleText(routingModuleInfo: IGenRoutingModuleInfo, distFilePath: string): string {
|
|
734
790
|
let content = "{\r\n";
|
|
735
791
|
content += ` path: "${routingModuleInfo.path}",\r\n`;
|
|
736
|
-
|
|
792
|
+
if (path.basename(distFilePath) !== "_routes.ts") {
|
|
793
|
+
content += ` component: ${routingModuleInfo.page.name},\r\n`;
|
|
794
|
+
}
|
|
737
795
|
if (routingModuleInfo.children.length > 0) {
|
|
738
796
|
content += ` children: [\r\n`;
|
|
739
797
|
for (const child of routingModuleInfo.children) {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
isMetadataGlobalReferenceExpression,
|
|
5
5
|
isMetadataImportedSymbolReferenceExpression,
|
|
6
6
|
isMetadataSymbolicCallExpression,
|
|
7
|
+
isMetadataSymbolicIfExpression,
|
|
7
8
|
isMetadataSymbolicReferenceExpression,
|
|
8
9
|
MetadataEntry,
|
|
9
10
|
MetadataObject,
|
|
@@ -17,7 +18,9 @@ export class SdAotMetadataReader {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
public getMetadatas(): IAotModuleDefMetadata {
|
|
20
|
-
if (StringUtil.isNullOrEmpty(this._metadataRoot.importAs))
|
|
21
|
+
if (StringUtil.isNullOrEmpty(this._metadataRoot.importAs)) {
|
|
22
|
+
throw new NeverEntryError();
|
|
23
|
+
}
|
|
21
24
|
|
|
22
25
|
const result: IAotModuleDefMetadata = {
|
|
23
26
|
moduleName: this._metadataRoot.importAs,
|
|
@@ -186,7 +189,7 @@ export class SdAotMetadataReader {
|
|
|
186
189
|
if (dec.arguments && dec.arguments.length !== 0) {
|
|
187
190
|
const paramObj = dec.arguments[0] as MetadataObject;
|
|
188
191
|
|
|
189
|
-
if (paramObj.providedIn
|
|
192
|
+
if (paramObj.providedIn != null) {
|
|
190
193
|
if (typeof paramObj.providedIn !== "string") throw new NeverEntryError();
|
|
191
194
|
result.providedIn = paramObj.providedIn;
|
|
192
195
|
}
|
|
@@ -255,6 +258,9 @@ export class SdAotMetadataReader {
|
|
|
255
258
|
);
|
|
256
259
|
result.push(...subProvRefTargets);
|
|
257
260
|
}
|
|
261
|
+
else if (isMetadataSymbolicIfExpression(refTarget.metadata)) {
|
|
262
|
+
result.push(...this._getProviderReferenceTargets([refTarget.metadata.thenExpression, refTarget.metadata.elseExpression]));
|
|
263
|
+
}
|
|
258
264
|
else {
|
|
259
265
|
throw new NeverEntryError();
|
|
260
266
|
}
|
|
@@ -7,6 +7,8 @@ import { Reference } from "@angular/compiler-cli/src/ngtsc/imports";
|
|
|
7
7
|
import { NgtscProgram } from "@angular/compiler-cli";
|
|
8
8
|
import * as path from "path";
|
|
9
9
|
import { INpmConfig } from "../../commons";
|
|
10
|
+
import { IMyModuleImport } from "./SdMyMetadataReader";
|
|
11
|
+
import { SdMetadataError } from "./SdMetadataError";
|
|
10
12
|
|
|
11
13
|
export class SdIvyMetadataReader {
|
|
12
14
|
private readonly _typeChecker: ts.TypeChecker;
|
|
@@ -76,7 +78,7 @@ export class SdIvyMetadataReader {
|
|
|
76
78
|
return result;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
private _getAliasedModuleImportInfo(identifier: ts.Identifier):
|
|
81
|
+
private _getAliasedModuleImportInfo(identifier: ts.Identifier): IMyModuleImport {
|
|
80
82
|
const moduleSymbol = this._typeChecker.getSymbolAtLocation(identifier);
|
|
81
83
|
if (!moduleSymbol) throw new NeverEntryError();
|
|
82
84
|
if (moduleSymbol.valueDeclaration) {
|
|
@@ -86,9 +88,18 @@ export class SdIvyMetadataReader {
|
|
|
86
88
|
else {
|
|
87
89
|
const aliasedTargetSymbol = this._typeChecker.getAliasedSymbol(moduleSymbol);
|
|
88
90
|
const declarations = aliasedTargetSymbol.getDeclarations();
|
|
89
|
-
if (!declarations
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
if (!declarations || declarations.length < 1) {
|
|
92
|
+
throw new SdMetadataError(this._sourceFile.fileName, `'${identifier.text}'를 찾을 수 없습니다.`);
|
|
93
|
+
}
|
|
94
|
+
const moduleFilePaths = declarations
|
|
95
|
+
.filter((item) => (
|
|
96
|
+
this._hasParentsOrMe(item, (item1) => Boolean(item1.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)))
|
|
97
|
+
))
|
|
98
|
+
.map((item) => PathUtil.posix(item.getSourceFile().fileName))
|
|
99
|
+
.distinct();
|
|
100
|
+
if (moduleFilePaths.length !== 1) {
|
|
101
|
+
throw new SdMetadataError(this._sourceFile.fileName, `'${identifier.text}'의 경로가 중복되었습니다.\n${moduleFilePaths.join("\n")}`);
|
|
102
|
+
}
|
|
92
103
|
|
|
93
104
|
const moduleFilePath = moduleFilePaths[0];
|
|
94
105
|
|
|
@@ -96,6 +107,18 @@ export class SdIvyMetadataReader {
|
|
|
96
107
|
}
|
|
97
108
|
}
|
|
98
109
|
|
|
110
|
+
private _hasParentsOrMe(node: ts.Node, fn: (node1: ts.Node) => boolean): boolean {
|
|
111
|
+
let currNode = node as ts.Node | undefined;
|
|
112
|
+
while (true) {
|
|
113
|
+
if (!currNode) return false;
|
|
114
|
+
|
|
115
|
+
const result = fn(currNode);
|
|
116
|
+
if (result) return true;
|
|
117
|
+
|
|
118
|
+
currNode = currNode.parent as ts.Node | undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
99
122
|
private getPackageName(): string {
|
|
100
123
|
let cursorDirPath = path.dirname(this._sourceFile.fileName);
|
|
101
124
|
while (true) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as ts from "typescript";
|
|
2
2
|
import { NeverEntryError } from "@simplysm/sd-core-common";
|
|
3
3
|
import { PathUtil } from "@simplysm/sd-core-node";
|
|
4
|
+
import { SdMetadataError } from "./SdMetadataError";
|
|
4
5
|
|
|
5
6
|
export class SdMyMetadataReader {
|
|
6
7
|
private readonly _typeChecker: ts.TypeChecker;
|
|
@@ -150,9 +151,18 @@ export class SdMyMetadataReader {
|
|
|
150
151
|
else {
|
|
151
152
|
const aliasedTargetSymbol = this._typeChecker.getAliasedSymbol(moduleSymbol);
|
|
152
153
|
const declarations = aliasedTargetSymbol.getDeclarations();
|
|
153
|
-
if (!declarations
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
if (!declarations || declarations.length < 1) {
|
|
155
|
+
throw new SdMetadataError(this._sourceFile.fileName, `'${identifier.text}'를 찾을 수 없습니다.`);
|
|
156
|
+
}
|
|
157
|
+
const moduleFilePaths = declarations
|
|
158
|
+
.filter((item) => (
|
|
159
|
+
this._hasParentsOrMe(item, (item1) => Boolean(item1.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)))
|
|
160
|
+
))
|
|
161
|
+
.map((item) => PathUtil.posix(item.getSourceFile().fileName))
|
|
162
|
+
.distinct();
|
|
163
|
+
if (moduleFilePaths.length !== 1) {
|
|
164
|
+
throw new SdMetadataError(this._sourceFile.fileName, `'${identifier.text}'의 경로가 중복되었습니다.\n${moduleFilePaths.join("\n")}`);
|
|
165
|
+
}
|
|
156
166
|
|
|
157
167
|
const moduleFilePath = moduleFilePaths[0];
|
|
158
168
|
|
|
@@ -160,6 +170,18 @@ export class SdMyMetadataReader {
|
|
|
160
170
|
}
|
|
161
171
|
}
|
|
162
172
|
|
|
173
|
+
private _hasParentsOrMe(node: ts.Node, fn: (node1: ts.Node) => boolean): boolean {
|
|
174
|
+
let currNode = node as ts.Node | undefined;
|
|
175
|
+
while (true) {
|
|
176
|
+
if (!currNode) return false;
|
|
177
|
+
|
|
178
|
+
const result = fn(currNode);
|
|
179
|
+
if (result) return true;
|
|
180
|
+
|
|
181
|
+
currNode = currNode.parent as ts.Node | undefined;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
163
185
|
private _getNgModuleDecoratorParam(decExp: ts.CallExpression): { exports: IMyModuleImport[]; providers: IMyModuleImport[] } {
|
|
164
186
|
const result: { exports: IMyModuleImport[]; providers: IMyModuleImport[] } = {
|
|
165
187
|
exports: [],
|