@simplysm/sd-cli 6.4.5 → 7.0.9
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 +11 -0
- package/dist/bin/sd-cli.d.ts +1 -0
- package/dist/bin/sd-cli.mjs +86 -0
- package/dist/build-tool/SdCliCacheCompilerHost.d.ts +10 -0
- package/dist/build-tool/SdCliCacheCompilerHost.mjs +44 -0
- package/dist/build-tool/SdCliNgCacheCompilerHost.d.ts +11 -0
- package/dist/build-tool/SdCliNgCacheCompilerHost.mjs +36 -0
- package/dist/build-tool/SdCliPackageLinter.d.ts +8 -0
- package/dist/build-tool/SdCliPackageLinter.mjs +41 -0
- package/dist/builder/SdCliJsLibBuilder.d.ts +14 -0
- package/dist/builder/SdCliJsLibBuilder.mjs +50 -0
- package/dist/builder/SdCliTsLibBuilder.d.ts +27 -0
- package/dist/builder/SdCliTsLibBuilder.mjs +226 -0
- package/dist/commons.d.ts +46 -0
- package/dist/commons.mjs +2 -0
- package/dist/entry-points/SdCliWorkspace.d.ts +18 -0
- package/dist/entry-points/SdCliWorkspace.mjs +193 -0
- package/dist/packages/SdCliPackage.d.ts +19 -0
- package/dist/packages/SdCliPackage.mjs +89 -0
- package/dist/utils/SdCliBuildResultUtil.d.ts +6 -0
- package/dist/utils/SdCliBuildResultUtil.mjs +38 -0
- package/dist/utils/SdCliConfigUtil.d.ts +7 -0
- package/dist/utils/SdCliConfigUtil.mjs +69 -0
- package/lib/ts-node-esm-paths.mjs +15 -0
- package/package.json +27 -59
- package/src/bin/sd-cli.ts +86 -214
- package/src/build-tool/SdCliCacheCompilerHost.ts +71 -0
- package/src/build-tool/SdCliNgCacheCompilerHost.ts +50 -0
- package/src/build-tool/SdCliPackageLinter.ts +54 -0
- package/src/builder/SdCliJsLibBuilder.ts +66 -0
- package/src/builder/SdCliTsLibBuilder.ts +335 -0
- package/src/commons.ts +17 -122
- package/src/entry-points/SdCliWorkspace.ts +229 -0
- package/src/packages/SdCliPackage.ts +111 -0
- package/src/utils/SdCliBuildResultUtil.ts +43 -0
- package/src/utils/SdCliConfigUtil.ts +94 -0
- package/tsconfig-build.json +9 -0
- package/tsconfig.json +7 -18
- package/.eslintrc.js +0 -19
- package/dist-node/bin/sd-cli.js +0 -197
- package/dist-node/bin/sd-cli.js.map +0 -1
- package/dist-node/build-tools/SdCliCordova.js +0 -144
- package/dist-node/build-tools/SdCliCordova.js.map +0 -1
- package/dist-node/build-tools/SdCliIndexFileGenerator.js +0 -51
- package/dist-node/build-tools/SdCliIndexFileGenerator.js.map +0 -1
- package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js +0 -675
- package/dist-node/build-tools/SdCliNgModuleFilesGenerator.js.map +0 -1
- package/dist-node/build-tools/metadata/SdAotMetadataReader.js +0 -274
- package/dist-node/build-tools/metadata/SdAotMetadataReader.js.map +0 -1
- package/dist-node/build-tools/metadata/SdIvyMetadataReader.js +0 -124
- package/dist-node/build-tools/metadata/SdIvyMetadataReader.js.map +0 -1
- package/dist-node/build-tools/metadata/SdMetadataError.js +0 -13
- package/dist-node/build-tools/metadata/SdMetadataError.js.map +0 -1
- package/dist-node/build-tools/metadata/SdMyMetadataReader.js +0 -321
- package/dist-node/build-tools/metadata/SdMyMetadataReader.js.map +0 -1
- package/dist-node/builders/SdCliJavascriptLinter.js +0 -65
- package/dist-node/builders/SdCliJavascriptLinter.js.map +0 -1
- package/dist-node/builders/SdCliNgClientBuilder.js +0 -636
- package/dist-node/builders/SdCliNgClientBuilder.js.map +0 -1
- package/dist-node/builders/SdCliNgLibraryBuilder.js +0 -217
- package/dist-node/builders/SdCliNgLibraryBuilder.js.map +0 -1
- package/dist-node/builders/SdCliPublisher.js +0 -129
- package/dist-node/builders/SdCliPublisher.js.map +0 -1
- package/dist-node/builders/SdCliServerBuilder.js +0 -452
- package/dist-node/builders/SdCliServerBuilder.js.map +0 -1
- package/dist-node/builders/SdCliTypescriptBuilder.js +0 -347
- package/dist-node/builders/SdCliTypescriptBuilder.js.map +0 -1
- package/dist-node/commons.js +0 -3
- package/dist-node/commons.js.map +0 -1
- package/dist-node/entry-points/SdCliLocalUpdater.js +0 -88
- package/dist-node/entry-points/SdCliLocalUpdater.js.map +0 -1
- package/dist-node/entry-points/SdCliPrepare.js +0 -56
- package/dist-node/entry-points/SdCliPrepare.js.map +0 -1
- package/dist-node/entry-points/SdCliProject.js +0 -302
- package/dist-node/entry-points/SdCliProject.js.map +0 -1
- package/dist-node/packages/SdCliClientPackage.js +0 -91
- package/dist-node/packages/SdCliClientPackage.js.map +0 -1
- package/dist-node/packages/SdCliLibraryPackage.js +0 -99
- package/dist-node/packages/SdCliLibraryPackage.js.map +0 -1
- package/dist-node/packages/SdCliPackageBase.js +0 -33
- package/dist-node/packages/SdCliPackageBase.js.map +0 -1
- package/dist-node/packages/SdCliServerPackage.js +0 -69
- package/dist-node/packages/SdCliServerPackage.js.map +0 -1
- package/dist-node/packages/SdCliUnknownPackage.js +0 -15
- package/dist-node/packages/SdCliUnknownPackage.js.map +0 -1
- package/dist-node/utils/SdCliFileCrypto.js +0 -76
- package/dist-node/utils/SdCliFileCrypto.js.map +0 -1
- package/dist-node/utils/SdProjectConfigUtil.js +0 -62
- package/dist-node/utils/SdProjectConfigUtil.js.map +0 -1
- package/dist-node/utils/SdTsDiagnosticUtil.js +0 -45
- package/dist-node/utils/SdTsDiagnosticUtil.js.map +0 -1
- package/dist-node/utils/SdWebpackUtil.js +0 -63
- package/dist-node/utils/SdWebpackUtil.js.map +0 -1
- package/dist-node/workers/client-ng-gen-worker.js +0 -57
- package/dist-node/workers/client-ng-gen-worker.js.map +0 -1
- package/dist-node/workers/lib-build-worker.js +0 -88
- package/dist-node/workers/lib-build-worker.js.map +0 -1
- package/dist-types/bin/sd-cli.d.ts +0 -3
- package/dist-types/bin/sd-cli.d.ts.map +0 -1
- package/dist-types/build-tools/SdCliCordova.d.ts +0 -15
- package/dist-types/build-tools/SdCliCordova.d.ts.map +0 -1
- package/dist-types/build-tools/SdCliIndexFileGenerator.d.ts +0 -13
- package/dist-types/build-tools/SdCliIndexFileGenerator.d.ts.map +0 -1
- package/dist-types/build-tools/SdCliNgModuleFilesGenerator.d.ts +0 -43
- package/dist-types/build-tools/SdCliNgModuleFilesGenerator.d.ts.map +0 -1
- package/dist-types/build-tools/metadata/SdAotMetadataReader.d.ts +0 -58
- package/dist-types/build-tools/metadata/SdAotMetadataReader.d.ts.map +0 -1
- package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts +0 -43
- package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts.map +0 -1
- package/dist-types/build-tools/metadata/SdMetadataError.d.ts +0 -7
- package/dist-types/build-tools/metadata/SdMetadataError.d.ts.map +0 -1
- package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts +0 -59
- package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts.map +0 -1
- package/dist-types/builders/SdCliJavascriptLinter.d.ts +0 -14
- package/dist-types/builders/SdCliJavascriptLinter.d.ts.map +0 -1
- package/dist-types/builders/SdCliNgClientBuilder.d.ts +0 -29
- package/dist-types/builders/SdCliNgClientBuilder.d.ts.map +0 -1
- package/dist-types/builders/SdCliNgLibraryBuilder.d.ts +0 -30
- package/dist-types/builders/SdCliNgLibraryBuilder.d.ts.map +0 -1
- package/dist-types/builders/SdCliPublisher.d.ts +0 -9
- package/dist-types/builders/SdCliPublisher.d.ts.map +0 -1
- package/dist-types/builders/SdCliServerBuilder.d.ts +0 -31
- package/dist-types/builders/SdCliServerBuilder.d.ts.map +0 -1
- package/dist-types/builders/SdCliTypescriptBuilder.d.ts +0 -56
- package/dist-types/builders/SdCliTypescriptBuilder.d.ts.map +0 -1
- package/dist-types/commons.d.ts +0 -134
- package/dist-types/commons.d.ts.map +0 -1
- package/dist-types/entry-points/SdCliLocalUpdater.d.ts +0 -12
- package/dist-types/entry-points/SdCliLocalUpdater.d.ts.map +0 -1
- package/dist-types/entry-points/SdCliPrepare.d.ts +0 -6
- package/dist-types/entry-points/SdCliPrepare.d.ts.map +0 -1
- package/dist-types/entry-points/SdCliProject.d.ts +0 -32
- package/dist-types/entry-points/SdCliProject.d.ts.map +0 -1
- package/dist-types/packages/SdCliClientPackage.d.ts +0 -17
- package/dist-types/packages/SdCliClientPackage.d.ts.map +0 -1
- package/dist-types/packages/SdCliLibraryPackage.d.ts +0 -20
- package/dist-types/packages/SdCliLibraryPackage.d.ts.map +0 -1
- package/dist-types/packages/SdCliPackageBase.d.ts +0 -11
- package/dist-types/packages/SdCliPackageBase.d.ts.map +0 -1
- package/dist-types/packages/SdCliServerPackage.d.ts +0 -16
- package/dist-types/packages/SdCliServerPackage.d.ts.map +0 -1
- package/dist-types/packages/SdCliUnknownPackage.d.ts +0 -9
- package/dist-types/packages/SdCliUnknownPackage.d.ts.map +0 -1
- package/dist-types/utils/SdCliFileCrypto.d.ts +0 -8
- package/dist-types/utils/SdCliFileCrypto.d.ts.map +0 -1
- package/dist-types/utils/SdProjectConfigUtil.d.ts +0 -7
- package/dist-types/utils/SdProjectConfigUtil.d.ts.map +0 -1
- package/dist-types/utils/SdTsDiagnosticUtil.d.ts +0 -6
- package/dist-types/utils/SdTsDiagnosticUtil.d.ts.map +0 -1
- package/dist-types/utils/SdWebpackUtil.d.ts +0 -7
- package/dist-types/utils/SdWebpackUtil.d.ts.map +0 -1
- package/dist-types/workers/client-ng-gen-worker.d.ts +0 -2
- package/dist-types/workers/client-ng-gen-worker.d.ts.map +0 -1
- package/dist-types/workers/lib-build-worker.d.ts +0 -2
- package/dist-types/workers/lib-build-worker.d.ts.map +0 -1
- package/schema/schema.json +0 -447
- package/sd-tsconfig.node.json +0 -18
- package/src/build-tools/SdCliCordova.ts +0 -240
- package/src/build-tools/SdCliIndexFileGenerator.ts +0 -61
- package/src/build-tools/SdCliNgModuleFilesGenerator.ts +0 -894
- package/src/build-tools/metadata/SdAotMetadataReader.ts +0 -374
- package/src/build-tools/metadata/SdIvyMetadataReader.ts +0 -183
- package/src/build-tools/metadata/SdMetadataError.ts +0 -7
- package/src/build-tools/metadata/SdMyMetadataReader.ts +0 -407
- package/src/builders/SdCliJavascriptLinter.ts +0 -81
- package/src/builders/SdCliNgClientBuilder.ts +0 -793
- package/src/builders/SdCliNgLibraryBuilder.ts +0 -301
- package/src/builders/SdCliPublisher.ts +0 -144
- package/src/builders/SdCliServerBuilder.ts +0 -555
- package/src/builders/SdCliTypescriptBuilder.ts +0 -552
- package/src/entry-points/SdCliLocalUpdater.ts +0 -114
- package/src/entry-points/SdCliPrepare.ts +0 -104
- package/src/entry-points/SdCliProject.ts +0 -405
- package/src/packages/SdCliClientPackage.ts +0 -111
- package/src/packages/SdCliLibraryPackage.ts +0 -118
- package/src/packages/SdCliPackageBase.ts +0 -34
- package/src/packages/SdCliServerPackage.ts +0 -85
- package/src/packages/SdCliUnknownPackage.ts +0 -14
- package/src/utils/SdCliFileCrypto.ts +0 -87
- package/src/utils/SdCliUtils.ts +0 -56
- package/src/utils/SdProjectConfigUtil.ts +0 -145
- package/src/utils/SdTsDiagnosticUtil.ts +0 -46
- package/src/utils/SdWebpackUtil.ts +0 -71
- package/src/workers/client-ng-gen-worker.ts +0 -63
- package/src/workers/lib-build-worker.ts +0 -97
|
@@ -1,894 +0,0 @@
|
|
|
1
|
-
import { ISdPackageBuildResult } from "../commons";
|
|
2
|
-
import { NeverEntryError, ObjectUtil, SdError, StringUtil } from "@simplysm/sd-core-common";
|
|
3
|
-
import * as ts from "typescript";
|
|
4
|
-
import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
|
|
5
|
-
import * as path from "path";
|
|
6
|
-
import { JSDOM } from "jsdom";
|
|
7
|
-
import * as os from "os";
|
|
8
|
-
import {
|
|
9
|
-
IMyComponentMetadata,
|
|
10
|
-
IMyDirectiveMetadata,
|
|
11
|
-
IMyInjectableMetadata,
|
|
12
|
-
IMyNgModuleMetadata,
|
|
13
|
-
IMyPipeMetadata,
|
|
14
|
-
SdMyMetadataReader,
|
|
15
|
-
TMyNgMetadata
|
|
16
|
-
} from "./metadata/SdMyMetadataReader";
|
|
17
|
-
import {
|
|
18
|
-
IAotComponentMetadata,
|
|
19
|
-
IAotDirectiveMetadata,
|
|
20
|
-
IAotModuleExport,
|
|
21
|
-
IAotNgModuleMetadata,
|
|
22
|
-
IAotPipeMetadata,
|
|
23
|
-
SdAotMetadataReader,
|
|
24
|
-
TAotNgMetadata
|
|
25
|
-
} from "./metadata/SdAotMetadataReader";
|
|
26
|
-
import { IIvyNgModuleMetadata, SdIvyMetadataReader, TIvyNgMetadata } from "./metadata/SdIvyMetadataReader";
|
|
27
|
-
import { NgtscProgram } from "@angular/compiler-cli";
|
|
28
|
-
import { SdMetadataError } from "./metadata/SdMetadataError";
|
|
29
|
-
|
|
30
|
-
// TODO: LazyPage??
|
|
31
|
-
export class SdCliNgModuleFilesGenerator {
|
|
32
|
-
private readonly _fileCache = new Map<string, TFileCache>();
|
|
33
|
-
|
|
34
|
-
private readonly _sourceDirPath = path.resolve(this._rootDir, "src");
|
|
35
|
-
private readonly _moduleDistDirPath = path.resolve(this._rootDir, "src/_modules");
|
|
36
|
-
|
|
37
|
-
private _compilerHost?: ts.CompilerHost;
|
|
38
|
-
private _moduleResolutionCache?: ts.ModuleResolutionCache;
|
|
39
|
-
private _program?: ts.Program;
|
|
40
|
-
|
|
41
|
-
public constructor(private readonly _rootDir: string) {
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
public deleteFileCaches(filePaths: string[]): void {
|
|
45
|
-
for (const filePath of filePaths) {
|
|
46
|
-
this._fileCache.delete(PathUtil.posix(filePath));
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public async reloadSourceFilesAsync(dirtyFilePaths: string[],
|
|
51
|
-
compilerHost: ts.CompilerHost,
|
|
52
|
-
moduleResolutionCache: ts.ModuleResolutionCache,
|
|
53
|
-
ngProgram: NgtscProgram): Promise<{ result: ISdPackageBuildResult[]; changed: boolean }> {
|
|
54
|
-
this._compilerHost = compilerHost;
|
|
55
|
-
this._moduleResolutionCache = moduleResolutionCache;
|
|
56
|
-
this._program = ngProgram.getTsProgram();
|
|
57
|
-
|
|
58
|
-
const result: ISdPackageBuildResult[] = [];
|
|
59
|
-
|
|
60
|
-
let changed = false;
|
|
61
|
-
for (const dirtyFilePath of dirtyFilePaths) {
|
|
62
|
-
try {
|
|
63
|
-
if (PathUtil.isChildPath(dirtyFilePath, this._moduleDistDirPath)) continue;
|
|
64
|
-
|
|
65
|
-
this._fileCache.delete(dirtyFilePath);
|
|
66
|
-
|
|
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
|
-
}
|
|
74
|
-
|
|
75
|
-
this._fileCache.set(dirtyFilePath, {
|
|
76
|
-
type: "my",
|
|
77
|
-
sourceFile,
|
|
78
|
-
metadata: new SdMyMetadataReader(sourceFile, this._program).getMetadatas()
|
|
79
|
-
});
|
|
80
|
-
changed = true;
|
|
81
|
-
}
|
|
82
|
-
|
|
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.fileName}(0, 0): error ${err.message}`
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
if (err instanceof Error) {
|
|
137
|
-
throw new SdError(err, "'" + dirtyFilePath + "' 메타데이터 로딩중 에러");
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
throw err;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return { result, changed };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
public async generateAsync(): Promise<{ result: ISdPackageBuildResult[]; changedFilePaths: string[] }> {
|
|
150
|
-
try {
|
|
151
|
-
let moduleInfoMap = this._getModuleInfoMap();
|
|
152
|
-
moduleInfoMap = this._mergeCircularModuleInfoMap(moduleInfoMap);
|
|
153
|
-
|
|
154
|
-
const routingModuleMap = await this._getRoutingModuleInfoMapAsync();
|
|
155
|
-
|
|
156
|
-
const changedFilePaths = [
|
|
157
|
-
...await this._writeNgModuleFileAsync(moduleInfoMap),
|
|
158
|
-
...await this._writeRoutingModuleFileAsync(moduleInfoMap, routingModuleMap)
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
const genFilePaths = [...moduleInfoMap.keys(), ...routingModuleMap.keys()].distinct();
|
|
162
|
-
const delFilePaths = (await FsUtil.globAsync(path.resolve(this._moduleDistDirPath, "**", "*")))
|
|
163
|
-
.filter((item) => (
|
|
164
|
-
!genFilePaths.includes(PathUtil.posix(item))
|
|
165
|
-
&& !genFilePaths.some((item1) => PathUtil.isChildPath(item1, item))
|
|
166
|
-
))
|
|
167
|
-
.map((item) => PathUtil.posix(item));
|
|
168
|
-
for (const delFilePath of delFilePaths) {
|
|
169
|
-
changedFilePaths.push(delFilePath);
|
|
170
|
-
await FsUtil.removeAsync(delFilePath);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return { result: [], changedFilePaths: changedFilePaths.distinct() };
|
|
174
|
-
}
|
|
175
|
-
catch (err) {
|
|
176
|
-
if (err instanceof SdMetadataError) {
|
|
177
|
-
return {
|
|
178
|
-
result: [{
|
|
179
|
-
filePath: err.fileName,
|
|
180
|
-
severity: "error",
|
|
181
|
-
message: `${err.fileName}(0, 0): error ${err.message}`
|
|
182
|
-
}],
|
|
183
|
-
changedFilePaths: []
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
else if (err instanceof Error) {
|
|
187
|
-
throw new SdError(err, "메타데이터 생성중 에러");
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
throw err;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// region NgModule
|
|
196
|
-
|
|
197
|
-
private _getModuleInfoMap(): Map<string, IGenNgModuleInfo> {
|
|
198
|
-
const moduleInfoMap = new Map<string, IGenNgModuleInfo>();
|
|
199
|
-
|
|
200
|
-
const ngModuleExportInfos = this._getAllNgModuleExportInfos();
|
|
201
|
-
const ngModuleExportMap = ngModuleExportInfos.groupBy((item) => item.exportModuleFilePath + "#" + item.exportName)
|
|
202
|
-
.toMap((item) => item.key, (item) => item.values);
|
|
203
|
-
|
|
204
|
-
for (const filePath of Array.from(this._fileCache.keys())) {
|
|
205
|
-
const fileCache = this._fileCache.get(filePath)!;
|
|
206
|
-
if (fileCache.type !== "my") continue;
|
|
207
|
-
|
|
208
|
-
for (const metadata of fileCache.metadata) {
|
|
209
|
-
if (
|
|
210
|
-
(
|
|
211
|
-
metadata.type === "Injectable"
|
|
212
|
-
&& (
|
|
213
|
-
metadata.className.endsWith("Provider")
|
|
214
|
-
&& metadata.providedIn !== "root"
|
|
215
|
-
)
|
|
216
|
-
)
|
|
217
|
-
|| (
|
|
218
|
-
metadata.type === "Directive"
|
|
219
|
-
&& metadata.className.endsWith("Directive")
|
|
220
|
-
)
|
|
221
|
-
|| (
|
|
222
|
-
metadata.type === "Pipe"
|
|
223
|
-
&& metadata.className.endsWith("Pipe")
|
|
224
|
-
)
|
|
225
|
-
|| (
|
|
226
|
-
metadata.type === "Component"
|
|
227
|
-
&& (
|
|
228
|
-
metadata.className.endsWith("Page")
|
|
229
|
-
|| metadata.className.endsWith("Component")
|
|
230
|
-
|| metadata.className.endsWith("Modal")
|
|
231
|
-
|| metadata.className.endsWith("Control")
|
|
232
|
-
|| metadata.className.endsWith("PrintTemplate")
|
|
233
|
-
|| metadata.className.endsWith("Toast")
|
|
234
|
-
)
|
|
235
|
-
)
|
|
236
|
-
) {
|
|
237
|
-
const newModuleInfo: IGenNgModuleInfo = {
|
|
238
|
-
moduleImportMap: new Map<string, string[]>(),
|
|
239
|
-
imports: [],
|
|
240
|
-
exports: [],
|
|
241
|
-
providers: [],
|
|
242
|
-
className: metadata.className + "Module"
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
if (metadata.type === "Injectable") {
|
|
246
|
-
newModuleInfo.providers.push({ moduleFilePath: filePath, name: metadata.className });
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
newModuleInfo.exports.push({ moduleFilePath: filePath, name: metadata.className });
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const moduleImport = newModuleInfo.moduleImportMap.getOrCreate(filePath, []);
|
|
253
|
-
moduleImport.push(metadata.className);
|
|
254
|
-
|
|
255
|
-
const ngModuleImportInfos = this._getNgModuleImportInfos(metadata, ngModuleExportMap);
|
|
256
|
-
for (const ngModuleImportInfo of ngModuleImportInfos) {
|
|
257
|
-
newModuleInfo.imports.push({ moduleFilePath: ngModuleImportInfo.filePath, name: ngModuleImportInfo.name });
|
|
258
|
-
const moduleImportMapValues = newModuleInfo.moduleImportMap.getOrCreate(ngModuleImportInfo.filePath, []);
|
|
259
|
-
moduleImportMapValues.push(ngModuleImportInfo.name);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
moduleInfoMap.set(
|
|
263
|
-
this._getNgModulePath(filePath, metadata.className),
|
|
264
|
-
{
|
|
265
|
-
moduleImportMap: Array.from(newModuleInfo.moduleImportMap.entries())
|
|
266
|
-
.toMap((item) => item[0], (item) => item[1].distinct()),
|
|
267
|
-
className: newModuleInfo.className,
|
|
268
|
-
imports: newModuleInfo.imports.distinct(),
|
|
269
|
-
exports: newModuleInfo.exports.distinct(),
|
|
270
|
-
providers: newModuleInfo.providers.distinct()
|
|
271
|
-
}
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// 변경 사항이 있으면 generate 다시 수행
|
|
278
|
-
|
|
279
|
-
const changed = this._reloadModuleInfoFileCache(moduleInfoMap);
|
|
280
|
-
if (changed) {
|
|
281
|
-
return this._getModuleInfoMap();
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return moduleInfoMap;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private _reloadModuleInfoFileCache(moduleInfoMap: Map<string, IGenNgModuleInfo>): boolean {
|
|
288
|
-
let changed = false;
|
|
289
|
-
for (const moduleInfoMapEntry of moduleInfoMap.entries()) {
|
|
290
|
-
const moduleFilePath = moduleInfoMapEntry[0];
|
|
291
|
-
const moduleInfo = moduleInfoMapEntry[1];
|
|
292
|
-
|
|
293
|
-
const newFileCache: IMyFileCache = {
|
|
294
|
-
type: "my",
|
|
295
|
-
sourceFile: undefined,
|
|
296
|
-
metadata: [
|
|
297
|
-
{
|
|
298
|
-
type: "NgModule",
|
|
299
|
-
className: moduleInfo.className,
|
|
300
|
-
exports: moduleInfo.exports,
|
|
301
|
-
providers: moduleInfo.providers
|
|
302
|
-
}
|
|
303
|
-
]
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const prevFileCache = this._fileCache.get(moduleFilePath);
|
|
307
|
-
if (!prevFileCache) {
|
|
308
|
-
this._fileCache.set(moduleFilePath, newFileCache);
|
|
309
|
-
changed = true;
|
|
310
|
-
}
|
|
311
|
-
else if (!ObjectUtil.equal(prevFileCache.metadata, newFileCache.metadata, { ignoreArrayIndex: true })) {
|
|
312
|
-
prevFileCache.metadata = newFileCache.metadata;
|
|
313
|
-
changed = true;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
return changed;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
private _mergeCircularModuleInfoMap(moduleInfoMap: Map<string, IGenNgModuleInfo>): Map<string, IGenNgModuleInfo> {
|
|
321
|
-
const result = ObjectUtil.clone(moduleInfoMap);
|
|
322
|
-
|
|
323
|
-
const fnMerge = (): boolean => {
|
|
324
|
-
const moduleFilePaths = Array.from(result.keys()).orderBy().orderBy((item) => item.length);
|
|
325
|
-
for (const moduleFilePath of moduleFilePaths) {
|
|
326
|
-
const circularFilePaths = this._getModuleInfoMapExportCircular(result, [moduleFilePath]);
|
|
327
|
-
if (circularFilePaths.length === 0) continue;
|
|
328
|
-
|
|
329
|
-
for (const circularFilePath of circularFilePaths) {
|
|
330
|
-
const thisModuleInfo = result.get(moduleFilePath)!;
|
|
331
|
-
const circularModuleInfo = result.get(circularFilePath)!;
|
|
332
|
-
|
|
333
|
-
const mergedModuleInfo = ObjectUtil.merge(circularModuleInfo, thisModuleInfo, { arrayProcess: "concat" });
|
|
334
|
-
mergedModuleInfo.moduleImportMap.delete(moduleFilePath);
|
|
335
|
-
mergedModuleInfo.moduleImportMap.delete(circularFilePath);
|
|
336
|
-
mergedModuleInfo.imports.remove((item) => item.moduleFilePath === moduleFilePath && item.name === thisModuleInfo.className);
|
|
337
|
-
mergedModuleInfo.imports.remove((item) => item.moduleFilePath === circularFilePath && item.name === circularModuleInfo.className);
|
|
338
|
-
|
|
339
|
-
result.set(moduleFilePath, mergedModuleInfo);
|
|
340
|
-
result.delete(circularFilePath);
|
|
341
|
-
this._fileCache.delete(circularFilePath);
|
|
342
|
-
|
|
343
|
-
for (const otherModuleInfoFilePath of result.keys()) {
|
|
344
|
-
const otherModuleInfo = result.get(otherModuleInfoFilePath)!;
|
|
345
|
-
if (otherModuleInfo.moduleImportMap.has(circularFilePath)) {
|
|
346
|
-
otherModuleInfo.moduleImportMap.set(moduleFilePath, [
|
|
347
|
-
...otherModuleInfo.moduleImportMap.get(moduleFilePath) ?? [],
|
|
348
|
-
thisModuleInfo.className
|
|
349
|
-
].distinct());
|
|
350
|
-
otherModuleInfo.moduleImportMap.delete(circularFilePath);
|
|
351
|
-
otherModuleInfo.imports.remove((item) => item.moduleFilePath === circularFilePath && item.name === circularModuleInfo.className);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
return true;
|
|
357
|
-
}
|
|
358
|
-
return false;
|
|
359
|
-
};
|
|
360
|
-
while (fnMerge()) {
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return result;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
private async _writeNgModuleFileAsync(moduleInfoMap: Map<string, IGenNgModuleInfo>): Promise<string[]> {
|
|
367
|
-
const changedDistFilePaths: string[] = [];
|
|
368
|
-
|
|
369
|
-
for (const distFilePath of moduleInfoMap.keys()) {
|
|
370
|
-
const moduleInfo = moduleInfoMap.get(distFilePath)!;
|
|
371
|
-
|
|
372
|
-
const moduleImportMap = Array.from(moduleInfo.moduleImportMap.entries())
|
|
373
|
-
.map((item) => ({
|
|
374
|
-
moduleName: this._getModuleModuleImportName(path.dirname(distFilePath), item[0]),
|
|
375
|
-
targetNames: item[1]
|
|
376
|
-
}))
|
|
377
|
-
.groupBy((item) => item.moduleName)
|
|
378
|
-
.toMap((item) => item.key, (item) => item.values.mapMany((v) => v.targetNames).distinct());
|
|
379
|
-
moduleImportMap.getOrCreate("@angular/core", []).push("NgModule");
|
|
380
|
-
moduleImportMap.getOrCreate("@angular/common", []).push("CommonModule");
|
|
381
|
-
|
|
382
|
-
const moduleImportTexts: string[] = [];
|
|
383
|
-
for (const moduleImportName of Array.from(moduleImportMap.keys()).orderBy()) {
|
|
384
|
-
const moduleImportInfo = moduleImportMap.get(moduleImportName)!.distinct();
|
|
385
|
-
if (moduleImportInfo.length === 0) continue;
|
|
386
|
-
moduleImportTexts.push(`import { ${moduleImportInfo.join(", ")} } from "${moduleImportName}";`);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const content = `
|
|
390
|
-
${moduleImportTexts.join(os.EOL)}
|
|
391
|
-
|
|
392
|
-
@NgModule({
|
|
393
|
-
imports: [${moduleInfo.imports.map((item) => item.name).concat(["CommonModule"]).distinct().orderBy().join(", ")}],
|
|
394
|
-
declarations: [${moduleInfo.exports.map((item) => item.name).distinct().orderBy().join(", ")}],
|
|
395
|
-
exports: [${moduleInfo.exports.map((item) => item.name).distinct().orderBy().join(", ")}],
|
|
396
|
-
providers: [${moduleInfo.providers.map((item) => item.name).distinct().orderBy().join(", ")}]
|
|
397
|
-
})
|
|
398
|
-
export class ${moduleInfo.className} {
|
|
399
|
-
}`.split("\n").map((item) => item.trimEnd()).join(os.EOL).trim();
|
|
400
|
-
|
|
401
|
-
if (!FsUtil.exists(distFilePath) || await FsUtil.readFileAsync(distFilePath) !== content) {
|
|
402
|
-
await FsUtil.writeFileAsync(distFilePath, content);
|
|
403
|
-
changedDistFilePaths.push(distFilePath);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return changedDistFilePaths;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
private _getNgModuleImportInfos(metadata: IMyInjectableMetadata | IMyDirectiveMetadata | IMyPipeMetadata | IMyComponentMetadata,
|
|
411
|
-
ngModuleExportMap: Map<string, INgModuleExportInfo[]>): { filePath: string; name: string }[] {
|
|
412
|
-
const importTargets: { filePath: string; name: string }[] = [];
|
|
413
|
-
|
|
414
|
-
// module import된 provider 찾기
|
|
415
|
-
for (const metadataModuleImport of metadata.moduleImports) {
|
|
416
|
-
importTargets.push({
|
|
417
|
-
filePath: metadataModuleImport.moduleFilePath,
|
|
418
|
-
name: metadataModuleImport.name
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if ("template" in metadata && !StringUtil.isNullOrEmpty(metadata.template)) {
|
|
423
|
-
// template으로 component/directive 찾기
|
|
424
|
-
const selectorInfos = this._getAllSelectorInfos();
|
|
425
|
-
const templateDOM = new JSDOM(metadata.template);
|
|
426
|
-
|
|
427
|
-
for (const selectorInfo of selectorInfos) {
|
|
428
|
-
if (
|
|
429
|
-
templateDOM.window.document.querySelector([
|
|
430
|
-
selectorInfo.selector,
|
|
431
|
-
selectorInfo.selector.replace(/\[/g, "[\\[").replace(/]/g, "\\]]"),
|
|
432
|
-
selectorInfo.selector.replace(/\[/g, "[\\(").replace(/]/g, "\\)]")
|
|
433
|
-
].join(", ")) != null
|
|
434
|
-
) {
|
|
435
|
-
importTargets.push({ filePath: selectorInfo.filePath, name: selectorInfo.className });
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// template으로 pipe 찾기
|
|
440
|
-
const pipeInfos = this._getAllPipeInfos();
|
|
441
|
-
|
|
442
|
-
for (const pipeInfo of pipeInfos) {
|
|
443
|
-
if (new RegExp("| *" + pipeInfo.name + "[^\\w]").test(metadata.template)) {
|
|
444
|
-
importTargets.push({ filePath: pipeInfo.filePath, name: pipeInfo.className });
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// provider/component/directive/pipe에 따라 NgModule 찾아 import등록
|
|
450
|
-
const result: { filePath: string; name: string }[] = [];
|
|
451
|
-
for (const importTarget of importTargets) {
|
|
452
|
-
const ngModules = ngModuleExportMap.get(importTarget.filePath + "#" + importTarget.name);
|
|
453
|
-
if (ngModules) {
|
|
454
|
-
if (ngModules.length !== 1) throw new NeverEntryError();
|
|
455
|
-
result.push({ filePath: ngModules[0].filePath, name: ngModules[0].className });
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
return result;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
private _getAllNgModuleExportInfos(): INgModuleExportInfo[] {
|
|
463
|
-
const result: INgModuleExportInfo[] = [];
|
|
464
|
-
|
|
465
|
-
for (const filePath of this._fileCache.keys()) {
|
|
466
|
-
const fileCache = this._fileCache.get(filePath)!;
|
|
467
|
-
if (fileCache.type === "my") {
|
|
468
|
-
const ngModules = fileCache.metadata.filter((item) => item.type === "NgModule") as IMyNgModuleMetadata[];
|
|
469
|
-
|
|
470
|
-
for (const ngModule of ngModules) {
|
|
471
|
-
for (const exp of ngModule.exports.concat(ngModule.providers)) {
|
|
472
|
-
result.push({
|
|
473
|
-
moduleName: undefined,
|
|
474
|
-
filePath,
|
|
475
|
-
className: ngModule.className,
|
|
476
|
-
exportModuleFilePath: exp.moduleFilePath,
|
|
477
|
-
exportName: exp.name
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
else if (fileCache.type === "aot") {
|
|
483
|
-
const ngModules = fileCache.metadata.filter((item) => item.type === "NgModule") as IAotNgModuleMetadata[];
|
|
484
|
-
|
|
485
|
-
for (const ngModule of ngModules) {
|
|
486
|
-
for (const exp of ngModule.exports.concat(ngModule.providers)) {
|
|
487
|
-
if (!StringUtil.isNullOrEmpty(exp.moduleName)) {
|
|
488
|
-
const newExp = this._getAotReferenceLastFilePath(filePath, exp.moduleName, exp.name);
|
|
489
|
-
if (!newExp) throw new NeverEntryError();
|
|
490
|
-
|
|
491
|
-
result.push({
|
|
492
|
-
moduleName: fileCache.moduleName,
|
|
493
|
-
filePath,
|
|
494
|
-
className: ngModule.className,
|
|
495
|
-
exportModuleFilePath: newExp.moduleFilePath,
|
|
496
|
-
exportName: newExp.name
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
else {
|
|
500
|
-
if (!fileCache.exports.some((item) => (item.as ?? item.name) === exp.name)) throw new NeverEntryError();
|
|
501
|
-
result.push({
|
|
502
|
-
moduleName: fileCache.moduleName,
|
|
503
|
-
filePath,
|
|
504
|
-
className: ngModule.className,
|
|
505
|
-
exportModuleFilePath: filePath,
|
|
506
|
-
exportName: exp.name
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
const ngModules = fileCache.metadata.filter((item) => item.type === "NgModule") as IIvyNgModuleMetadata[];
|
|
514
|
-
|
|
515
|
-
for (const ngModule of ngModules) {
|
|
516
|
-
for (const exp of ngModule.exports) {
|
|
517
|
-
result.push({
|
|
518
|
-
moduleName: fileCache.moduleName,
|
|
519
|
-
filePath,
|
|
520
|
-
className: ngModule.className,
|
|
521
|
-
exportModuleFilePath: exp.moduleFilePath,
|
|
522
|
-
exportName: exp.name
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
return result.distinct();
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
private _getModuleInfoMapExportCircular(moduleInfoMap: Map<string, IGenNgModuleInfo>, arr: string[]): string[] {
|
|
533
|
-
if (moduleInfoMap.has(arr.last()!)) {
|
|
534
|
-
const moduleInfo = moduleInfoMap.get(arr.last()!)!;
|
|
535
|
-
|
|
536
|
-
const result: string[] = [];
|
|
537
|
-
for (const moduleImportFilePath of moduleInfo.moduleImportMap.keys()) {
|
|
538
|
-
if (arr.includes(moduleImportFilePath)) {
|
|
539
|
-
if (arr[0] === moduleImportFilePath) {
|
|
540
|
-
result.push(...arr.slice(1));
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
result.push(...this._getModuleInfoMapExportCircular(moduleInfoMap, arr.concat([moduleImportFilePath])));
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
return result.distinct();
|
|
548
|
-
}
|
|
549
|
-
else {
|
|
550
|
-
return [];
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
private _getNgModulePath(pageFilePath: string, pageClassName: string): string {
|
|
555
|
-
return PathUtil.posix(this._getGenNgModuleDistPath(pageFilePath), pageClassName + "Module.ts");
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
private _getAotReferenceLastFilePath(filePath: string, moduleName: string, targetName: string): { moduleFilePath: string; name: string } | undefined {
|
|
559
|
-
const expFilePath = this._getResolvedFilePath(filePath, moduleName);
|
|
560
|
-
if (StringUtil.isNullOrEmpty(expFilePath)) throw new NeverEntryError();
|
|
561
|
-
const expFileCache = this._fileCache.get(expFilePath);
|
|
562
|
-
if (!expFileCache) {
|
|
563
|
-
this._fileCache.get(expFilePath.replace(/[\\/]/g, "\\"));
|
|
564
|
-
throw new SdMetadataError(filePath, `'${moduleName}'에 대한 파일 '${expFilePath}'을 찾을 수 없습니다.`);
|
|
565
|
-
}
|
|
566
|
-
if (expFileCache.type !== "aot") throw new NeverEntryError();
|
|
567
|
-
const newExp = expFileCache.exports.single((item) => (item.as ?? item.name) === targetName);
|
|
568
|
-
if (!newExp) throw new NeverEntryError();
|
|
569
|
-
|
|
570
|
-
if (!StringUtil.isNullOrEmpty(newExp.moduleName)) {
|
|
571
|
-
return this._getAotReferenceLastFilePath(expFilePath, newExp.moduleName, newExp.name!);
|
|
572
|
-
}
|
|
573
|
-
else {
|
|
574
|
-
return {
|
|
575
|
-
moduleFilePath: expFilePath,
|
|
576
|
-
name: newExp.as ?? newExp.name!
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
private _getAllSelectorInfos(): { selector: string; className: string; filePath: string }[] {
|
|
582
|
-
const result: { selector: string; className: string; filePath: string }[] = [];
|
|
583
|
-
|
|
584
|
-
for (const filePath of this._fileCache.keys()) {
|
|
585
|
-
const fileCache = this._fileCache.get(filePath)!;
|
|
586
|
-
|
|
587
|
-
const selectorMetadata = (fileCache.metadata as ((TAotNgMetadata | TMyNgMetadata)[]))
|
|
588
|
-
.filter((item) => item.type === "Component" || item.type === "Directive") as (IMyComponentMetadata | IMyDirectiveMetadata | IAotComponentMetadata | IAotDirectiveMetadata)[];
|
|
589
|
-
|
|
590
|
-
for (const selectorMetadataItem of selectorMetadata) {
|
|
591
|
-
if (StringUtil.isNullOrEmpty(selectorMetadataItem.selector)) continue;
|
|
592
|
-
|
|
593
|
-
result.push(({
|
|
594
|
-
selector: selectorMetadataItem.selector,
|
|
595
|
-
className: selectorMetadataItem.className,
|
|
596
|
-
filePath
|
|
597
|
-
}));
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
return result;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
private _getAllPipeInfos(): { name: string; className: string; filePath: string }[] {
|
|
604
|
-
const result: { name: string; className: string; filePath: string }[] = [];
|
|
605
|
-
for (const filePath of this._fileCache.keys()) {
|
|
606
|
-
const fileCache = this._fileCache.get(filePath)!;
|
|
607
|
-
|
|
608
|
-
const pipeMetadata = (fileCache.metadata as ((TAotNgMetadata | TMyNgMetadata)[]))
|
|
609
|
-
.filter((item) => item.type === "Component" || item.type === "Directive") as (IMyPipeMetadata | IAotPipeMetadata)[];
|
|
610
|
-
|
|
611
|
-
for (const pipeMetadataItem of pipeMetadata) {
|
|
612
|
-
if (StringUtil.isNullOrEmpty(pipeMetadataItem.name)) continue;
|
|
613
|
-
|
|
614
|
-
result.push(({
|
|
615
|
-
name: pipeMetadataItem.name,
|
|
616
|
-
className: pipeMetadataItem.className,
|
|
617
|
-
filePath
|
|
618
|
-
}));
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
return result;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
private _getModuleModuleImportName(distDirPath: string, filePath: string): string {
|
|
625
|
-
const fileCache = this._fileCache.get(filePath);
|
|
626
|
-
const presetModuleName = !fileCache || fileCache.type === "my" ? undefined : fileCache.moduleName;
|
|
627
|
-
if (!StringUtil.isNullOrEmpty(presetModuleName)) return presetModuleName;
|
|
628
|
-
|
|
629
|
-
const relativeFilePath = PathUtil.posix(path.relative(distDirPath, filePath));
|
|
630
|
-
return (relativeFilePath.startsWith(".") ? relativeFilePath : "./" + relativeFilePath)
|
|
631
|
-
.replace(/\.ts$/, "")
|
|
632
|
-
.replace(/\\/g, "/");
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
private _getResolvedFilePath(sourceFilePath: string, moduleName: string): string | undefined {
|
|
636
|
-
const resolvedModule = ts.resolveModuleName(
|
|
637
|
-
moduleName,
|
|
638
|
-
sourceFilePath,
|
|
639
|
-
this._program!.getCompilerOptions(),
|
|
640
|
-
this._compilerHost!,
|
|
641
|
-
this._moduleResolutionCache
|
|
642
|
-
).resolvedModule;
|
|
643
|
-
|
|
644
|
-
if (resolvedModule) {
|
|
645
|
-
return PathUtil.posix(resolvedModule.resolvedFileName);
|
|
646
|
-
}
|
|
647
|
-
return undefined;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
private _getGenNgModuleDistPath(filePath: string): string {
|
|
651
|
-
return path.resolve(this._moduleDistDirPath, path.relative(this._sourceDirPath, path.dirname(filePath)));
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// endregion
|
|
655
|
-
|
|
656
|
-
// region RoutingModule
|
|
657
|
-
|
|
658
|
-
private async _getRoutingModuleInfoMapAsync(): Promise<Map<string, IGenRoutingModuleInfo>> {
|
|
659
|
-
const result = new Map<string, IGenRoutingModuleInfo>();
|
|
660
|
-
|
|
661
|
-
for (const filePath of Array.from(this._fileCache.keys())) {
|
|
662
|
-
const fileCache = this._fileCache.get(filePath)!;
|
|
663
|
-
if (fileCache.type !== "my") continue;
|
|
664
|
-
|
|
665
|
-
for (const metadata of fileCache.metadata) {
|
|
666
|
-
if (!metadata.className.endsWith("Page")) continue;
|
|
667
|
-
|
|
668
|
-
const newRoutingModuleInfo: IGenRoutingModuleInfo = {
|
|
669
|
-
path: "",
|
|
670
|
-
page: {
|
|
671
|
-
moduleFilePath: filePath,
|
|
672
|
-
name: metadata.className
|
|
673
|
-
},
|
|
674
|
-
children: []
|
|
675
|
-
};
|
|
676
|
-
|
|
677
|
-
const childDirName = StringUtil.toKebabCase(path.basename(filePath, path.extname(filePath)).replace(/Page$/, ""));
|
|
678
|
-
const childDirPath = path.resolve(path.dirname(filePath), childDirName);
|
|
679
|
-
if (FsUtil.exists(childDirPath)) {
|
|
680
|
-
newRoutingModuleInfo.children = await this._getRoutingModuleChildInfoAsync(childDirPath);
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
result.set(
|
|
684
|
-
this._getRoutingModulePath(filePath, metadata.className),
|
|
685
|
-
newRoutingModuleInfo
|
|
686
|
-
);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
return result;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
private async _getRoutingModuleChildInfoAsync(childDirPath: string): Promise<IGenRoutingChildModuleInfo[]> {
|
|
694
|
-
const result: IGenRoutingChildModuleInfo[] = [];
|
|
695
|
-
|
|
696
|
-
const childDirChildPaths = (await FsUtil.readdirAsync(childDirPath)).map((item) => path.resolve(childDirPath, item));
|
|
697
|
-
|
|
698
|
-
const ignoreDirPaths: string[] = [];
|
|
699
|
-
for (const childDirChildPath of childDirChildPaths) {
|
|
700
|
-
if (childDirChildPath.endsWith("Page.ts")) {
|
|
701
|
-
const childDirChildDirName = StringUtil.toKebabCase(path.basename(childDirChildPath, path.extname(childDirChildPath)).replace(/Page$/, ""));
|
|
702
|
-
result.push({
|
|
703
|
-
path: childDirChildDirName,
|
|
704
|
-
page: {
|
|
705
|
-
moduleFilePath: childDirChildPath,
|
|
706
|
-
name: path.basename(childDirChildPath, path.extname(childDirChildPath))
|
|
707
|
-
}
|
|
708
|
-
});
|
|
709
|
-
ignoreDirPaths.push(path.resolve(path.dirname(childDirChildPath), childDirChildDirName));
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
for (const childDirChildPath of childDirChildPaths) {
|
|
714
|
-
if (FsUtil.isDirectory(childDirChildPath) && !ignoreDirPaths.includes(childDirChildPath)) {
|
|
715
|
-
result.push({
|
|
716
|
-
path: path.basename(childDirChildPath),
|
|
717
|
-
children: await this._getRoutingModuleChildInfoAsync(childDirChildPath)
|
|
718
|
-
});
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
return result;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
private async _writeRoutingModuleFileAsync(moduleInfoMap: Map<string, IGenNgModuleInfo>, routingModuleInfoMap: Map<string, IGenRoutingModuleInfo>): Promise<string[]> {
|
|
726
|
-
const changedDistFilePaths: string[] = [];
|
|
727
|
-
for (const distFilePath of routingModuleInfoMap.keys()) {
|
|
728
|
-
const routingModuleInfo = routingModuleInfoMap.get(distFilePath)!;
|
|
729
|
-
|
|
730
|
-
const routingModuleText = this._getRoutingModuleText(routingModuleInfo, distFilePath);
|
|
731
|
-
|
|
732
|
-
const moduleImportTexts: string[] = [];
|
|
733
|
-
|
|
734
|
-
const pageFilePath = this._getModuleModuleImportName(path.dirname(distFilePath), routingModuleInfo.page.moduleFilePath);
|
|
735
|
-
|
|
736
|
-
let content: string;
|
|
737
|
-
if (path.basename(distFilePath) === "_routes.ts") {
|
|
738
|
-
moduleImportTexts.push(`import { Routes } from "@angular/router";`);
|
|
739
|
-
|
|
740
|
-
content = `
|
|
741
|
-
${moduleImportTexts.join(os.EOL)}
|
|
742
|
-
|
|
743
|
-
export const routes: Routes = [
|
|
744
|
-
${routingModuleText.replace(/\r\n/g, "\r\n ")}
|
|
745
|
-
];`.split("\n").map((item) => item.trimEnd()).join(os.EOL).trim();
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
moduleImportTexts.push(`import { NgModule } from "@angular/core";`);
|
|
749
|
-
moduleImportTexts.push(`import { RouterModule } from "@angular/router";`);
|
|
750
|
-
if (path.basename(distFilePath) !== "_routes.ts") {
|
|
751
|
-
moduleImportTexts.push(`import { SdCanDeactivateGuardProvider } from "@simplysm/sd-angular";`);
|
|
752
|
-
}
|
|
753
|
-
moduleImportTexts.push(`import { ${routingModuleInfo.page.name} } from "${pageFilePath}";`);
|
|
754
|
-
|
|
755
|
-
const thisPageModuleInfoEntry = Array.from(moduleInfoMap.entries())
|
|
756
|
-
.single((item) => item[1].exports.some((exp) => exp.moduleFilePath === routingModuleInfo.page.moduleFilePath && exp.name === routingModuleInfo.page.name));
|
|
757
|
-
if (!thisPageModuleInfoEntry) throw new NeverEntryError();
|
|
758
|
-
const thisPageModuleInfo = {
|
|
759
|
-
filePath: thisPageModuleInfoEntry[0],
|
|
760
|
-
className: thisPageModuleInfoEntry[1].className
|
|
761
|
-
};
|
|
762
|
-
|
|
763
|
-
const pageNgModuleFilePath = this._getModuleModuleImportName(path.dirname(distFilePath), thisPageModuleInfo.filePath);
|
|
764
|
-
moduleImportTexts.push(`import { ${thisPageModuleInfo.className} } from "${pageNgModuleFilePath}";`);
|
|
765
|
-
|
|
766
|
-
content = `
|
|
767
|
-
${moduleImportTexts.join(os.EOL)}
|
|
768
|
-
|
|
769
|
-
@NgModule({
|
|
770
|
-
imports: [
|
|
771
|
-
${thisPageModuleInfo.className},
|
|
772
|
-
RouterModule.forChild([
|
|
773
|
-
${routingModuleText.replace(/\r\n/g, "\r\n ")}
|
|
774
|
-
])
|
|
775
|
-
]
|
|
776
|
-
})
|
|
777
|
-
export class ${routingModuleInfo.page.name}RoutingModule {
|
|
778
|
-
}`.split("\n").map((item) => item.trimEnd()).join(os.EOL).trim();
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
if (!FsUtil.exists(distFilePath) || await FsUtil.readFileAsync(distFilePath) !== content) {
|
|
782
|
-
await FsUtil.writeFileAsync(distFilePath, content);
|
|
783
|
-
changedDistFilePaths.push(distFilePath);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
return changedDistFilePaths;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
private _getRoutingModulePath(pageFilePath: string, pageClassName: string): string {
|
|
791
|
-
if (pageFilePath === PathUtil.posix(this._sourceDirPath, "AppPage.ts")) {
|
|
792
|
-
return PathUtil.posix(this._sourceDirPath, "_routes.ts");
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
return PathUtil.posix(this._getGenNgModuleDistPath(pageFilePath), pageClassName + "RoutingModule.ts");
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
private _getRoutingModuleText(routingModuleInfo: IGenRoutingModuleInfo, distFilePath: string): string {
|
|
800
|
-
let content = "{\r\n";
|
|
801
|
-
content += ` path: "${routingModuleInfo.path}",\r\n`;
|
|
802
|
-
if (path.basename(distFilePath) !== "_routes.ts") {
|
|
803
|
-
content += ` component: ${routingModuleInfo.page.name},\r\n`;
|
|
804
|
-
content += ` canDeactivate: [SdCanDeactivateGuardProvider],\r\n`;
|
|
805
|
-
}
|
|
806
|
-
if (routingModuleInfo.children.length > 0) {
|
|
807
|
-
content += ` children: [\r\n`;
|
|
808
|
-
for (const child of routingModuleInfo.children) {
|
|
809
|
-
const childText = this._getRoutingModuleChildText(child, path.dirname(distFilePath));
|
|
810
|
-
content += " " + childText.replace(/\r\n/g, "\r\n ") + ",\r\n";
|
|
811
|
-
}
|
|
812
|
-
content = content.slice(0, -3) + "\r\n";
|
|
813
|
-
content += ` ],\r\n`;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
return content.slice(0, -3) + "\r\n}";
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
private _getRoutingModuleChildText(routingModuleChildInfo: IGenRoutingChildModuleInfo, distDirPath: string): string {
|
|
820
|
-
let content = "{\r\n";
|
|
821
|
-
content += ` path: "${routingModuleChildInfo.path}",\r\n`;
|
|
822
|
-
if (routingModuleChildInfo.page) {
|
|
823
|
-
const routingModuleFilePath = this._getRoutingModulePath(routingModuleChildInfo.page.moduleFilePath, routingModuleChildInfo.page.name);
|
|
824
|
-
|
|
825
|
-
const moduleDirPath = "./" + PathUtil.posix(path.dirname(path.relative(distDirPath, routingModuleFilePath)));
|
|
826
|
-
|
|
827
|
-
content += ` loadChildren: async () => await import("${moduleDirPath}/${routingModuleChildInfo.page.name}RoutingModule").then((m) => m.${routingModuleChildInfo.page.name}RoutingModule),\r\n`;
|
|
828
|
-
}
|
|
829
|
-
else if (routingModuleChildInfo.children && routingModuleChildInfo.children.length > 0) {
|
|
830
|
-
content += ` children: [\r\n`;
|
|
831
|
-
for (const child of routingModuleChildInfo.children) {
|
|
832
|
-
const childText = this._getRoutingModuleChildText(child, distDirPath);
|
|
833
|
-
content += " " + childText.replace(/\r\n/g, "\r\n ") + ",\r\n";
|
|
834
|
-
}
|
|
835
|
-
content = content.slice(0, -3) + "\r\n";
|
|
836
|
-
content += ` ],\r\n`;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
return content.slice(0, -3) + "\r\n}";
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
// endregion
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
type TFileCache = IMyFileCache | IAotFileCache | IIvyFileCache;
|
|
846
|
-
|
|
847
|
-
interface IMyFileCache {
|
|
848
|
-
type: "my";
|
|
849
|
-
sourceFile?: ts.SourceFile;
|
|
850
|
-
metadata: TMyNgMetadata[];
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
interface IAotFileCache {
|
|
854
|
-
type: "aot";
|
|
855
|
-
sourceFile: ts.SourceFile;
|
|
856
|
-
moduleName: string;
|
|
857
|
-
exports: IAotModuleExport[];
|
|
858
|
-
metadata: TAotNgMetadata[];
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
interface IIvyFileCache {
|
|
862
|
-
type: "ivy";
|
|
863
|
-
sourceFile: ts.SourceFile;
|
|
864
|
-
moduleName: string;
|
|
865
|
-
metadata: TIvyNgMetadata[];
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
interface IGenNgModuleInfo {
|
|
869
|
-
moduleImportMap: Map<string, string[]>;
|
|
870
|
-
imports: { moduleFilePath: string; name: string }[];
|
|
871
|
-
exports: { moduleFilePath: string; name: string }[];
|
|
872
|
-
providers: { moduleFilePath: string; name: string }[];
|
|
873
|
-
className: string;
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
interface IGenRoutingModuleInfo {
|
|
877
|
-
path: string;
|
|
878
|
-
page: { moduleFilePath: string; name: string };
|
|
879
|
-
children: IGenRoutingChildModuleInfo[];
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
interface IGenRoutingChildModuleInfo {
|
|
883
|
-
path: string;
|
|
884
|
-
page?: { moduleFilePath: string; name: string };
|
|
885
|
-
children?: IGenRoutingChildModuleInfo[];
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
interface INgModuleExportInfo {
|
|
889
|
-
moduleName: string | undefined;
|
|
890
|
-
filePath: string;
|
|
891
|
-
className: string;
|
|
892
|
-
exportModuleFilePath: string;
|
|
893
|
-
exportName: string;
|
|
894
|
-
}
|