@simplysm/sd-cli 7.0.248 → 7.0.266

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/README.md +95 -0
  2. package/assets/client-files/assets/icons/icon-128x128.png +0 -0
  3. package/assets/client-files/assets/icons/icon-144x144.png +0 -0
  4. package/assets/client-files/assets/icons/icon-152x152.png +0 -0
  5. package/assets/client-files/assets/icons/icon-192x192.png +0 -0
  6. package/assets/client-files/assets/icons/icon-384x384.png +0 -0
  7. package/assets/client-files/assets/icons/icon-512x512.png +0 -0
  8. package/assets/client-files/assets/icons/icon-72x72.png +0 -0
  9. package/assets/client-files/assets/icons/icon-96x96.png +0 -0
  10. package/assets/client-files/favicon.ico +0 -0
  11. package/dist/bin/sd-cli.mjs +212 -15
  12. package/dist/build-tool/SdCliCordova.mjs +3 -3
  13. package/dist/build-tool/SdCliElectron.mjs +3 -2
  14. package/dist/build-tool/SdCliIndexFileGenerator.mjs +2 -3
  15. package/dist/builder/SdCliClientBuilder.d.ts +2 -0
  16. package/dist/builder/SdCliClientBuilder.mjs +55 -18
  17. package/dist/builder/SdCliServerBuilder.d.ts +2 -0
  18. package/dist/builder/SdCliServerBuilder.mjs +27 -13
  19. package/dist/builder/SdCliTsLibBuilder.mjs +18 -12
  20. package/dist/commons.d.ts +6 -1
  21. package/dist/entry-points/SdCliPrepare.mjs +34 -34
  22. package/dist/entry-points/SdCliProjectGenerator.d.ts +44 -0
  23. package/dist/entry-points/SdCliProjectGenerator.mjs +320 -0
  24. package/dist/entry-points/SdCliWorkspace.d.ts +6 -6
  25. package/dist/entry-points/SdCliWorkspace.mjs +61 -107
  26. package/dist/entry-points/file/base/fc_package_eslintrc.d.ts +3 -0
  27. package/dist/entry-points/file/base/fc_package_eslintrc.mjs +31 -0
  28. package/dist/entry-points/file/base/fc_package_npmconfig.d.ts +9 -0
  29. package/dist/entry-points/file/base/fc_package_npmconfig.mjs +32 -0
  30. package/dist/entry-points/file/base/fc_package_tsconfig.d.ts +5 -0
  31. package/dist/entry-points/file/base/fc_package_tsconfig.mjs +13 -0
  32. package/dist/entry-points/file/client/fc_package_AppModule.d.ts +1 -0
  33. package/dist/entry-points/file/client/fc_package_AppModule.mjs +37 -0
  34. package/dist/entry-points/file/client/fc_package_AppPage.d.ts +1 -0
  35. package/dist/entry-points/file/client/fc_package_AppPage.mjs +14 -0
  36. package/dist/entry-points/file/client/fc_package_Page.d.ts +4 -0
  37. package/dist/entry-points/file/client/fc_package_Page.mjs +19 -0
  38. package/dist/entry-points/file/client/fc_package_client_main.d.ts +1 -0
  39. package/dist/entry-points/file/client/fc_package_client_main.mjs +19 -0
  40. package/dist/entry-points/file/client/fc_package_index.d.ts +3 -0
  41. package/dist/entry-points/file/client/fc_package_index.mjs +88 -0
  42. package/dist/entry-points/file/client/fc_package_manifest.d.ts +5 -0
  43. package/dist/entry-points/file/client/fc_package_manifest.mjs +54 -0
  44. package/dist/entry-points/file/client/fc_package_polyfills.d.ts +1 -0
  45. package/dist/entry-points/file/client/fc_package_polyfills.mjs +11 -0
  46. package/dist/entry-points/file/client/fc_package_styles.d.ts +1 -0
  47. package/dist/entry-points/file/client/fc_package_styles.mjs +7 -0
  48. package/dist/entry-points/file/db/fc_package_DbContext.d.ts +3 -0
  49. package/dist/entry-points/file/db/fc_package_DbContext.mjs +14 -0
  50. package/dist/entry-points/file/db/fc_package_DbModel.d.ts +4 -0
  51. package/dist/entry-points/file/db/fc_package_DbModel.mjs +12 -0
  52. package/dist/entry-points/file/project/fc_project_editor_config.d.ts +1 -0
  53. package/dist/entry-points/file/project/fc_project_editor_config.mjs +22 -0
  54. package/dist/entry-points/file/project/fc_project_eslintrc.d.ts +1 -0
  55. package/dist/entry-points/file/project/fc_project_eslintrc.mjs +30 -0
  56. package/dist/entry-points/file/project/fc_project_gitattributes.d.ts +1 -0
  57. package/dist/entry-points/file/project/fc_project_gitattributes.mjs +6 -0
  58. package/dist/entry-points/file/project/fc_project_gitignore.d.ts +1 -0
  59. package/dist/entry-points/file/project/fc_project_gitignore.mjs +17 -0
  60. package/dist/entry-points/file/project/fc_project_npmconfig.d.ts +7 -0
  61. package/dist/entry-points/file/project/fc_project_npmconfig.mjs +35 -0
  62. package/dist/entry-points/file/project/fc_project_readme.d.ts +3 -0
  63. package/dist/entry-points/file/project/fc_project_readme.mjs +13 -0
  64. package/dist/entry-points/file/project/fc_project_simplysm.d.ts +1 -0
  65. package/dist/entry-points/file/project/fc_project_simplysm.mjs +2 -0
  66. package/dist/entry-points/file/project/fc_project_tsconfig.d.ts +1 -0
  67. package/dist/entry-points/file/project/fc_project_tsconfig.mjs +26 -0
  68. package/dist/entry-points/file/server/fc_package_server_main.d.ts +4 -0
  69. package/dist/entry-points/file/server/fc_package_server_main.mjs +60 -0
  70. package/dist/index.d.ts +23 -0
  71. package/dist/index.mjs +24 -1
  72. package/dist/ng-tools/SdCliNgModuleGenerator.mjs +35 -36
  73. package/dist/packages/SdCliPackage.d.ts +1 -0
  74. package/dist/packages/SdCliPackage.mjs +69 -63
  75. package/dist/utils/SdCliBuildResultUtil.mjs +2 -2
  76. package/docs/client-add-page.md +8 -0
  77. package/docs/client-router.md +85 -0
  78. package/docs/client-sw.md +101 -0
  79. package/docs/conf-orm.md +81 -0
  80. package/docs/conf-usage.md +5 -0
  81. package/docs/lib-local-update.md +50 -0
  82. package/docs/lib-ts-paths.md +25 -0
  83. package/package.json +10 -8
  84. package/src/SdCliBuildResultError.ts +9 -9
  85. package/src/bin/sd-cli.ts +244 -15
  86. package/src/build-tool/SdCliCacheCompilerHost.ts +77 -77
  87. package/src/build-tool/SdCliCordova.ts +2 -2
  88. package/src/build-tool/SdCliElectron.ts +2 -1
  89. package/src/build-tool/SdCliGithubApi.ts +110 -110
  90. package/src/build-tool/SdCliIndexFileGenerator.ts +79 -80
  91. package/src/build-tool/SdCliNgCacheCompilerHost.ts +58 -58
  92. package/src/build-tool/SdCliPackageLinter.ts +74 -74
  93. package/src/builder/SdCliClientBuilder.ts +71 -20
  94. package/src/builder/SdCliJsLibBuilder.ts +70 -70
  95. package/src/builder/SdCliServerBuilder.ts +34 -14
  96. package/src/builder/SdCliTsLibBuilder.ts +450 -445
  97. package/src/commons.ts +6 -1
  98. package/src/entry-points/SdCliFileCrypto.ts +87 -87
  99. package/src/entry-points/SdCliPrepare.ts +55 -55
  100. package/src/entry-points/SdCliProjectGenerator.ts +395 -0
  101. package/src/entry-points/SdCliWorkspace.ts +74 -122
  102. package/src/entry-points/file/base/fc_package_eslintrc.ts +30 -0
  103. package/src/entry-points/file/base/fc_package_npmconfig.ts +43 -0
  104. package/src/entry-points/file/base/fc_package_tsconfig.ts +12 -0
  105. package/src/entry-points/file/client/fc_package_AppModule.ts +36 -0
  106. package/src/entry-points/file/client/fc_package_AppPage.ts +13 -0
  107. package/src/entry-points/file/client/fc_package_Page.ts +19 -0
  108. package/src/entry-points/file/client/fc_package_client_main.ts +18 -0
  109. package/src/entry-points/file/client/fc_package_index.ts +87 -0
  110. package/src/entry-points/file/client/fc_package_manifest.ts +53 -0
  111. package/src/entry-points/file/client/fc_package_polyfills.ts +10 -0
  112. package/src/entry-points/file/client/fc_package_styles.ts +6 -0
  113. package/src/entry-points/file/db/fc_package_DbContext.ts +14 -0
  114. package/src/entry-points/file/db/fc_package_DbModel.ts +11 -0
  115. package/src/entry-points/file/project/fc_project_editor_config.ts +21 -0
  116. package/src/entry-points/file/project/fc_project_eslintrc.ts +29 -0
  117. package/src/entry-points/file/project/fc_project_gitattributes.ts +5 -0
  118. package/src/entry-points/file/project/fc_project_gitignore.ts +16 -0
  119. package/src/entry-points/file/project/fc_project_npmconfig.ts +34 -0
  120. package/src/entry-points/file/project/fc_project_readme.ts +12 -0
  121. package/src/entry-points/file/project/fc_project_simplysm.ts +1 -0
  122. package/src/entry-points/file/project/fc_project_tsconfig.ts +25 -0
  123. package/src/entry-points/file/server/fc_package_server_main.ts +62 -0
  124. package/src/index.ts +55 -32
  125. package/src/ng-tools/SdCliNgModuleGenerator.ts +639 -640
  126. package/src/ng-tools/babel/SdCliBbFileMetadata.ts +568 -568
  127. package/src/ng-tools/babel/SdCliBbRootMetadata.ts +239 -239
  128. package/src/ng-tools/babel/SdCliBbUtil.ts +15 -15
  129. package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +234 -234
  130. package/src/ng-tools/babel/TSdCliBbTypeMetadata.ts +177 -177
  131. package/src/ng-tools/commons.ts +3 -3
  132. package/src/ng-tools/typescript/SdCliTsFileMetadata.ts +384 -384
  133. package/src/ng-tools/typescript/SdCliTsRootMetadata.ts +32 -32
  134. package/src/ng-tools/typescript/SdCliTsUtil.ts +29 -29
  135. package/src/packages/SdCliPackage.ts +76 -59
  136. package/src/utils/SdCliBuildResultUtil.ts +76 -76
  137. package/src/utils/SdCliConfigUtil.ts +94 -94
  138. package/src/utils/SdCliNpmConfigUtil.ts +16 -16
@@ -0,0 +1,395 @@
1
+ import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
2
+ import path from "path";
3
+ import { StringUtil } from "@simplysm/sd-core-common";
4
+ import { fc_project_editor_config } from "./file/project/fc_project_editor_config";
5
+ import { fc_project_eslintrc } from "./file/project/fc_project_eslintrc";
6
+ import { fc_project_gitignore } from "./file/project/fc_project_gitignore";
7
+ import { fc_project_gitattributes } from "./file/project/fc_project_gitattributes";
8
+ import { fc_project_npmconfig } from "./file/project/fc_project_npmconfig";
9
+ import { fc_project_readme } from "./file/project/fc_project_readme";
10
+ import { fc_project_simplysm } from "./file/project/fc_project_simplysm";
11
+ import { fc_project_tsconfig } from "./file/project/fc_project_tsconfig";
12
+ import { fc_package_eslintrc } from "./file/base/fc_package_eslintrc";
13
+ import { fc_package_npmconfig } from "./file/base/fc_package_npmconfig";
14
+ import { fc_package_tsconfig } from "./file/base/fc_package_tsconfig";
15
+ import { fc_package_DbContext } from "./file/db/fc_package_DbContext";
16
+ import { fc_package_DbModel } from "./file/db/fc_package_DbModel";
17
+ import { fc_package_server_main } from "./file/server/fc_package_server_main";
18
+ import { fc_package_AppModule } from "./file/client/fc_package_AppModule";
19
+ import { fc_package_AppPage } from "./file/client/fc_package_AppPage";
20
+ import { fileURLToPath } from "url";
21
+ import { fc_package_index } from "./file/client/fc_package_index";
22
+ import { fc_package_client_main } from "./file/client/fc_package_client_main";
23
+ import { fc_package_manifest } from "./file/client/fc_package_manifest";
24
+ import { INpmConfig } from "../commons";
25
+ import { fc_package_polyfills } from "./file/client/fc_package_polyfills";
26
+ import { fc_package_styles } from "./file/client/fc_package_styles";
27
+ import { ISdAutoIndexConfig } from "../build-tool/SdCliIndexFileGenerator";
28
+ import { fc_package_Page } from "./file/client/fc_package_Page";
29
+
30
+ export class SdCliProjectGenerator {
31
+ private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
32
+
33
+ public constructor(private readonly _rootPath: string) {
34
+ }
35
+
36
+ public async initAsync(opt: { name?: string; description: string; author: string; gitUrl: string }): Promise<void> {
37
+ if ((await FsUtil.readdirAsync(this._rootPath)).filter((item) => ![".idea", "package.json", "node_modules", "package-lock.json"].includes(path.basename(item))).length > 0) {
38
+ throw new Error("빈 디렉토리가 아닙니다. (package-lock.json, package.json, node_modules 외의 파일/폴더가 존재하는 경우, 초기화할 수 없습니다.)");
39
+ }
40
+
41
+ const projName = opt.name ?? path.basename(this._rootPath);
42
+
43
+ this._logger.log("'.editorconfig' 파일 생성");
44
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, ".editorconfig"), fc_project_editor_config());
45
+
46
+ this._logger.log(`[${projName}] '.eslintrc.cjs' 파일 생성`);
47
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, ".eslintrc.cjs"), fc_project_eslintrc());
48
+
49
+ this._logger.log(`[${projName}]'.gitattributes' 파일 생성`);
50
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, ".gitattributes"), fc_project_gitattributes());
51
+
52
+ this._logger.log(`[${projName}] '.gitignore' 파일 생성`);
53
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, ".gitignore"), fc_project_gitignore());
54
+
55
+ this._logger.log(`[${projName}] 'package.json' 파일 생성`);
56
+ let cliVersion: string | undefined;
57
+ if (FsUtil.exists(path.resolve(this._rootPath, "package.json"))) {
58
+ const npmConfig = await FsUtil.readJsonAsync(path.resolve(this._rootPath, "package.json")) as INpmConfig;
59
+ cliVersion = npmConfig.dependencies?.["@simplysm/sd-cli"];
60
+ }
61
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, "package.json"), fc_project_npmconfig({
62
+ name: projName,
63
+ description: opt.description,
64
+ author: opt.author,
65
+ gitUrl: opt.gitUrl,
66
+ cliVersion
67
+ }));
68
+
69
+ this._logger.log(`[${projName}] 'README.md' 파일 생성`);
70
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, "README.md"), fc_project_readme({
71
+ description: opt.description
72
+ }));
73
+
74
+ this._logger.log(`[${projName}] 'simplysm.json' 파일 생성`);
75
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, "simplysm.json"), fc_project_simplysm());
76
+
77
+ this._logger.log(`[${projName}] 'tsconfig.json' 파일 생성`);
78
+ await FsUtil.writeFileAsync(path.resolve(this._rootPath, "tsconfig.json"), fc_project_tsconfig());
79
+
80
+ this._logger.log(`[${projName}] 'packages' 디렉토리 생성`);
81
+ await FsUtil.mkdirsAsync(path.resolve(this._rootPath, "packages"));
82
+
83
+ this._logger.log(`[${projName}] npm install`);
84
+ await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
85
+ }
86
+
87
+ public async addTsLibAsync(opt: { name: string; description: string; useDom: boolean; isForAngular: boolean }): Promise<void> {
88
+ const projNpmConfig = await this._getProjNpmConfigAsync();
89
+ const projName = projNpmConfig.name;
90
+
91
+ await this._addPackageBaseTemplate({
92
+ name: opt.name,
93
+ description: opt.description,
94
+ useDom: opt.isForAngular || opt.useDom,
95
+ isForAngular: opt.isForAngular,
96
+ isModule: true,
97
+ types: "dist/index.d.ts",
98
+ main: "dist/index.mjs",
99
+ dependencies: {},
100
+ tsconfigOptions: {}
101
+ });
102
+
103
+ this._logger.log(`[${opt.name}] 'simplysm.json' 파일에 등록`);
104
+
105
+ await this._addPackageToSimplysmJson({
106
+ name: opt.name,
107
+ type: "library",
108
+ autoIndex: {
109
+ ...opt.isForAngular ? {
110
+ polyfills: [
111
+ "@simplysm/sd-core-common",
112
+ "@simplysm/sd-core-browser"
113
+ ]
114
+ } : {}
115
+ },
116
+ });
117
+
118
+ this._logger.log(`[${projName}] npm install`);
119
+ await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
120
+ }
121
+
122
+ public async addDbLibAsync(opt: { name: string }): Promise<void> {
123
+ const pkgName = "db-" + opt.name;
124
+ const pkgPath = path.resolve(this._rootPath, "packages", pkgName);
125
+ const projNpmConfig = await this._getProjNpmConfigAsync();
126
+ const projName = projNpmConfig.name;
127
+
128
+ await this._addPackageBaseTemplate({
129
+ name: pkgName,
130
+ description: "DB " + opt.name.toUpperCase(),
131
+ useDom: false,
132
+ isModule: false,
133
+ isForAngular: false,
134
+ types: "dist/index.d.ts",
135
+ main: "dist/index.cjs",
136
+ dependencies: {
137
+ "@simplysm/sd-core-common": "~7.0.0",
138
+ "@simplysm/sd-orm-common": "~7.0.0"
139
+ },
140
+ tsconfigOptions: {}
141
+ });
142
+
143
+ this._logger.log(`[${pkgName}] 'src/${StringUtil.toPascalCase(opt.name)}DbContext.ts' 파일 생성`);
144
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, `src/${StringUtil.toPascalCase(opt.name)}DbContext.ts`), fc_package_DbContext({
145
+ name: opt.name
146
+ }));
147
+
148
+ this._logger.log(`[${pkgName}] 'src/models' 디렉토리 생성`);
149
+ await FsUtil.mkdirsAsync(path.resolve(pkgPath, "src/models"));
150
+
151
+ this._logger.log(`[${pkgName}] 'simplysm.json' 파일에 등록`);
152
+ await this._addPackageToSimplysmJson({
153
+ name: pkgName,
154
+ type: "library",
155
+ autoIndex: {}
156
+ });
157
+
158
+ this._logger.log(`[${projName}] npm install`);
159
+ await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
160
+ }
161
+
162
+ public async addDbLibModelAsync(opt: { dbPkgName: string; category: string; name: string; description: string }): Promise<void> {
163
+ const pkgName = "db-" + opt.dbPkgName;
164
+ const pkgPath = path.resolve(this._rootPath, "packages", pkgName);
165
+
166
+ this._logger.log(`[${pkgName}] 'src/models/${opt.category}/${opt.name}.ts' 파일 생성`);
167
+
168
+ await FsUtil.writeFileAsync(
169
+ path.resolve(pkgPath, `src/models/${opt.category}/${opt.name}.ts`),
170
+ fc_package_DbModel({
171
+ name: opt.name,
172
+ description: opt.description
173
+ })
174
+ );
175
+
176
+ this._logger.log(`[${pkgName}] DbContext 파일에 등록`);
177
+ let dbContextContent = await FsUtil.readFileAsync(path.resolve(pkgPath, `src/${StringUtil.toPascalCase(opt.dbPkgName)}DbContext.ts`));
178
+
179
+ if (!dbContextContent.includes(`Queryable`)) {
180
+ this._logger.log(`[${pkgName}] DbContext 파일에 등록: import: Queryable`);
181
+ dbContextContent = dbContextContent.replace(/ } from "@simplysm\/sd-orm-common";/, `, Queryable } from "@simplysm/sd-orm-common";`);
182
+ }
183
+
184
+ this._logger.log(`[${pkgName}] DbContext 파일에 등록: import: MODEL`);
185
+ dbContextContent = `import { ${opt.name} } from "./models/${opt.category}/${opt.name}";\n` + dbContextContent;
186
+
187
+ if (!dbContextContent.includes(`//-- ${opt.category}\n`)) {
188
+ this._logger.log(`[${opt.name}] DbContext 파일에 등록: CATEGORY`);
189
+
190
+ dbContextContent = dbContextContent.replace(/\n}/, `\n\n //-- ${opt.category}\n}`);
191
+ }
192
+
193
+ this._logger.log(`[${pkgName}] DbContext 파일에 등록: MODEL`);
194
+
195
+ dbContextContent = dbContextContent.replace(new RegExp(`//-- ${opt.category}\n`), `
196
+ //-- ${opt.category}
197
+ public readonly ${StringUtil.toCamelCase(opt.name)} = new Queryable(this, ${opt.name});
198
+ `.trim() + "\n");
199
+
200
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, `src/${StringUtil.toPascalCase(opt.dbPkgName)}DbContext.ts`), dbContextContent);
201
+ }
202
+
203
+ public async addServerAsync(opt: { name?: string; description?: string }): Promise<void> {
204
+ const pkgName = "server" + (opt.name === undefined ? "" : `-${opt.name}`);
205
+ const pkgPath = path.resolve(this._rootPath, "packages", pkgName);
206
+ const projNpmConfig = await this._getProjNpmConfigAsync();
207
+ const projName = projNpmConfig.name;
208
+
209
+ await this._addPackageBaseTemplate({
210
+ name: pkgName,
211
+ description: (opt.description === undefined ? "" : `${opt.description.toUpperCase()} `) + "서버",
212
+ useDom: false,
213
+ isModule: false,
214
+ isForAngular: false,
215
+ main: "dist/main.js",
216
+ dependencies: {
217
+ "@simplysm/sd-core-common": "~7.0.0",
218
+ "@simplysm/sd-core-node": "~7.0.0",
219
+ "@simplysm/sd-service-common": "~7.0.0",
220
+ "@simplysm/sd-service-server": "~7.0.0"
221
+ },
222
+ tsconfigOptions: {}
223
+ });
224
+
225
+ this._logger.log(`[${pkgName}] 'src/main.ts' 파일 등록`);
226
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, `src/main.ts`), fc_package_server_main({
227
+ projPath: this._rootPath,
228
+ pkgName: pkgName
229
+ }));
230
+
231
+ this._logger.log(`[${pkgName}] 'simplysm.json' 파일에 등록`);
232
+ await this._addPackageToSimplysmJson({
233
+ name: pkgName,
234
+ type: "server"
235
+ });
236
+
237
+ this._logger.log(`[${projName}] npm install`);
238
+ await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
239
+ }
240
+
241
+ public async addClientAsync(opt: { name: string; description: string; serverName: string }): Promise<void> {
242
+ const pkgName = `client-${opt.name}`;
243
+ const pkgPath = path.resolve(this._rootPath, "packages", pkgName);
244
+
245
+ const projNpmConfig = await this._getProjNpmConfigAsync();
246
+ const projName = projNpmConfig.name;
247
+
248
+ await this._addPackageBaseTemplate({
249
+ name: pkgName,
250
+ description: `${opt.description} 클라이언트`,
251
+ useDom: true,
252
+ isModule: true,
253
+ isForAngular: true,
254
+ dependencies: {
255
+ "@angular/platform-browser": "^13.2.0",
256
+ "@angular/platform-browser-dynamic": "^13.2.0"
257
+ },
258
+ tsconfigOptions: {
259
+ angularCompilerOptions: {
260
+ "enableI18nLegacyMessageIdFormat": false,
261
+ "strictInjectionParameters": true,
262
+ "strictInputAccessModifiers": true,
263
+ "strictTemplates": true,
264
+ "strictInputTypes": false,
265
+ "strictOutputEventTypes": false
266
+ }
267
+ }
268
+ });
269
+
270
+ this._logger.log(`[${pkgName}] 'src/AppModule.ts' 파일 등록`);
271
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/AppModule.ts"), fc_package_AppModule());
272
+
273
+ this._logger.log(`[${pkgName}] 'src/AppPage.ts' 파일 등록`);
274
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/AppPage.ts"), fc_package_AppPage());
275
+
276
+ this._logger.log(`[${pkgName}] 'src/index.html' 파일 등록`);
277
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/index.html"), fc_package_index({
278
+ description: opt.description
279
+ }));
280
+
281
+ this._logger.log(`[${pkgName}] 'src/main.ts' 파일 등록`);
282
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/main.ts"), fc_package_client_main());
283
+
284
+ this._logger.log(`[${pkgName}] 'src/manifest.json' 파일 등록`);
285
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/manifest.json"), fc_package_manifest({
286
+ description: projNpmConfig.description,
287
+ author: projNpmConfig.author,
288
+ version: projNpmConfig.version
289
+ }));
290
+
291
+ this._logger.log(`[${pkgName}] 'src/polyfills.ts' 파일 등록`);
292
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/polyfills.ts"), fc_package_polyfills());
293
+
294
+ this._logger.log(`[${pkgName}] 'src/styles.scss' 파일 등록`);
295
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/styles.scss"), fc_package_styles());
296
+
297
+ this._logger.log(`[${pkgName}] 'src/assets' 파일 복사`);
298
+ await FsUtil.copyAsync(
299
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../assets/client-files"),
300
+ path.resolve(pkgPath, "src")
301
+ );
302
+
303
+ await this._addPackageToSimplysmJson({
304
+ name: pkgName,
305
+ type: "client",
306
+ serverName: opt.serverName
307
+ });
308
+
309
+ this._logger.log(`[${projName}] npm install`);
310
+ await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
311
+ }
312
+
313
+ public async addPageAsync(opt: { pkgName: string; category?: string; name: string; isRouteParent: boolean }): Promise<void> {
314
+ const pkgPath = path.resolve(this._rootPath, "packages", opt.pkgName);
315
+
316
+ this._logger.log(`[${opt.pkgName}] 'src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${opt.name}Page.ts' 파일 생성`);
317
+ await FsUtil.writeFileAsync(
318
+ path.resolve(pkgPath, `src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${opt.name}Page.ts`),
319
+ fc_package_Page({
320
+ name: opt.name,
321
+ isRouteParent: opt.isRouteParent
322
+ })
323
+ );
324
+
325
+ if (opt.isRouteParent) {
326
+ this._logger.log(`[${opt.name}] 'src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${StringUtil.toKebabCase(opt.name)}' 디렉토리 생성`);
327
+ await FsUtil.mkdirsAsync(path.resolve(pkgPath, `src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${StringUtil.toKebabCase(opt.name)}`));
328
+ }
329
+ }
330
+
331
+ private async _addPackageBaseTemplate(opt: { name: string; description: string; useDom: boolean; isModule: boolean; isForAngular: boolean; main?: string; types?: string; dependencies: Record<string, string>; tsconfigOptions: Record<string, any> }): Promise<void> {
332
+ const pkgPath = path.resolve(this._rootPath, "packages", opt.name);
333
+
334
+ this._logger.log(`[${opt.name}] '.eslintrc.cjs' 파일 생성`);
335
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, ".eslintrc.cjs"), fc_package_eslintrc({
336
+ isForAngular: opt.isForAngular
337
+ }));
338
+
339
+ this._logger.log(`[${opt.name}] 'package.json' 파일 생성`);
340
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "package.json"), fc_package_npmconfig({
341
+ projPath: this._rootPath,
342
+ name: opt.name,
343
+ description: opt.description,
344
+ isModule: opt.isModule,
345
+ main: opt.main,
346
+ types: opt.types,
347
+ dependencies: {
348
+ ...opt.dependencies,
349
+ ...opt.isForAngular ? {
350
+ "@angular/common": "^13.2.0",
351
+ "@angular/core": "^13.2.0",
352
+ "@simplysm/sd-angular": "~7.0.0",
353
+ "@simplysm/sd-core-common": "~7.0.0",
354
+ "@simplysm/sd-core-browser": "~7.0.0",
355
+ "rxjs": "^6.6.7",
356
+ "zone.js": "~0.11.4"
357
+ } : {}
358
+ }
359
+ }));
360
+
361
+ this._logger.log(`[${opt.name}] 'tsconfig.json' 파일 생성`);
362
+ await FsUtil.writeFileAsync(path.resolve(pkgPath, "tsconfig.json"), fc_package_tsconfig({
363
+ isModule: opt.isModule,
364
+ useDom: opt.useDom,
365
+ options: opt.tsconfigOptions
366
+ }));
367
+
368
+ this._logger.log(`[${opt.name}] 'src' 디렉토리 생성`);
369
+ await FsUtil.mkdirsAsync(path.resolve(pkgPath, "src"));
370
+ }
371
+
372
+ private async _addPackageToSimplysmJson(opt: { name: string; type: string; autoIndex?: ISdAutoIndexConfig; serverName?: string }): Promise<void> {
373
+ const config = await FsUtil.readJsonAsync(path.resolve(this._rootPath, "simplysm.json"));
374
+ config.packages = config.packages ?? {};
375
+ config.packages[opt.name] = {
376
+ type: opt.type,
377
+ ...opt.autoIndex ? { autoIndex: opt.autoIndex } : {},
378
+ ...opt.serverName !== undefined ? { server: opt.serverName } : {}
379
+ };
380
+ await FsUtil.writeJsonAsync(path.resolve(this._rootPath, "simplysm.json"), config, { space: 2 });
381
+ }
382
+
383
+ private async _getProjNpmConfigAsync(): Promise<INpmConfig & { description: string; author: string }> {
384
+ const projNpmConfig = await FsUtil.readJsonAsync(path.resolve(this._rootPath, "package.json")) as INpmConfig;
385
+
386
+ if (projNpmConfig.description === undefined) {
387
+ throw new Error("프로젝트 package.json 파일에 description 이 설정되어있지 않습니다.");
388
+ }
389
+ if (projNpmConfig.author === undefined) {
390
+ throw new Error("프로젝트 package.json 파일에 author 가 설정되어있지 않습니다.");
391
+ }
392
+
393
+ return projNpmConfig as any;
394
+ }
395
+ }
@@ -32,7 +32,8 @@ export class SdCliWorkspace {
32
32
  }
33
33
 
34
34
  this._logger.debug("패키지 목록 구성...");
35
- const pkgs = await this._getPackagesAsync(config, opt.pkgs);
35
+ const allPkgs = await this._getPackagesAsync(config);
36
+ const pkgs = allPkgs.filter((pkg) => opt.pkgs.length === 0 || opt.pkgs.includes(path.basename(pkg.rootPath)));
36
37
 
37
38
  this._logger.debug("패키지 이벤트 설정...");
38
39
  let changeCount = 0;
@@ -102,32 +103,6 @@ export class SdCliWorkspace {
102
103
  if (pkg.config.type === "client") {
103
104
  await pkg.watchAsync();
104
105
 
105
- /*const pkgMiddleware: NextHandleFunction = (req, res, next) => {
106
- if (req.method === "GET") {
107
- const urlObj = url.parse(req.url!, true, false);
108
- const urlPathChain = decodeURI(urlObj.pathname!.slice(1)).split("/");
109
- if (urlPathChain[0] === pkg.name.split("/").last()!) {
110
- let targetFilePath = path.resolve(pkg.rootPath, "dist", ...urlPathChain.slice(1));
111
- targetFilePath = FsUtil.exists(targetFilePath) && FsUtil.stat(targetFilePath).isDirectory() ? path.resolve(targetFilePath, "index.html") : targetFilePath;
112
-
113
- if (FsUtil.exists(targetFilePath) && !path.basename(targetFilePath).startsWith(".")) {
114
- const fileStream = FsUtil.createReadStream(targetFilePath);
115
- const targetFileSize = FsUtil.lstat(targetFilePath).size;
116
-
117
- fileStream.on("open", () => {
118
- res.setHeader("Content-Length", targetFileSize);
119
- res.setHeader("Content-Type", mime.getType(targetFilePath)!);
120
- res.writeHead(200);
121
- });
122
- fileStream.pipe(res);
123
- return;
124
- }
125
- }
126
- }
127
-
128
- next();
129
- };*/
130
-
131
106
  if (typeof pkg.config.server === "string") {
132
107
  const serverInfo = this._serverInfoMap.getOrCreate(pkg.config.server, { pathProxy: [], clientInfos: [] });
133
108
 
@@ -164,20 +139,6 @@ export class SdCliWorkspace {
164
139
  platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
165
140
  cordovaTargets: pkg.config.builder?.cordova?.target ? Object.keys(pkg.config.builder.cordova.target) : ["browser"]
166
141
  });
167
-
168
- /*const server = new SdServiceServer({
169
- rootPath: process.cwd(),
170
- services: [],
171
- port: pkg.config.server.port
172
- });
173
- await server.listenAsync();
174
- serverInfo.server = server;
175
- serverInfo.server.devMiddlewares = [pkgMiddleware];
176
- serverInfo.clientInfos.push({
177
- pkgKey: pkg.name.split("/").last()!,
178
- platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
179
- cordovaTargets: pkg.config.builder?.cordova?.target ? Object.keys(pkg.config.builder.cordova.target) : ["browser"]
180
- });*/
181
142
  }
182
143
  }
183
144
  }
@@ -201,6 +162,76 @@ export class SdCliWorkspace {
201
162
  }
202
163
  }
203
164
 
165
+ public async buildAsync(opt: { confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
166
+ this._logger.debug("프로젝트 설정 가져오기...");
167
+ const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
168
+
169
+ this._logger.debug("패키지 목록 구성...");
170
+ const allPkgs = await this._getPackagesAsync(config);
171
+ const pkgs = allPkgs.filter((pkg) => opt.pkgs.length === 0 || opt.pkgs.includes(path.basename(pkg.rootPath)));
172
+
173
+ this._logger.debug("프로젝트 및 패키지 버전 설정...");
174
+ await this._upgradeVersionAsync(allPkgs);
175
+
176
+ // 빌드
177
+ await this._buildPkgsAsync(pkgs);
178
+ }
179
+
180
+ public async publishAsync(opt: { noBuild: boolean; confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
181
+ this._logger.debug("프로젝트 설정 가져오기...");
182
+ const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
183
+
184
+ if (opt.noBuild) {
185
+ this._logger.warn("빌드하지 않고, 배포하는것은 상당히 위험합니다.");
186
+ await this._waitSecMessageAsync("프로세스를 중지하려면, 'CTRL+C'를 누르세요.", 5);
187
+ }
188
+
189
+ // GIT 사용중일 경우, 커밋되지 않은 수정사항이 있는지 확인
190
+ if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
191
+ this._logger.debug("GIT 커밋여부 확인...");
192
+ const gitStatusResult = await SdProcess.spawnAsync("git status");
193
+ if (gitStatusResult.includes("Changes") || gitStatusResult.includes("Untracked")) {
194
+ throw new Error("커밋되지 않은 정보가 있습니다.\n" + gitStatusResult);
195
+ }
196
+ }
197
+
198
+ this._logger.debug("패키지 목록 구성...");
199
+ const allPkgs = await this._getPackagesAsync(config);
200
+ const pkgs = allPkgs.filter((pkg) => opt.pkgs.length === 0 || opt.pkgs.includes(path.basename(pkg.rootPath)));
201
+
202
+ this._logger.debug("프로젝트 및 패키지 버전 설정...");
203
+ await this._upgradeVersionAsync(allPkgs);
204
+
205
+ // 빌드
206
+ if (!opt.noBuild) {
207
+ // this._logger.debug("노드패키지 업데이트...");
208
+ // await new SdCliNpm(this._rootPath).updateAsync();
209
+
210
+ this._logger.debug("빌드를 시작합니다...");
211
+ await this._buildPkgsAsync(pkgs);
212
+ }
213
+
214
+ // GIT 사용중일경우, 새 버전 커밋 및 TAG 생성
215
+ if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
216
+ this._logger.debug("새 버전 커밋 및 TAG 생성...");
217
+ await SdProcess.spawnAsync("git add .");
218
+ await SdProcess.spawnAsync(`git commit -m "v${this._npmConfig.version}"`);
219
+ await SdProcess.spawnAsync(`git tag -a "v${this._npmConfig.version}" -m "v${this._npmConfig.version}"`);
220
+
221
+ this._logger.debug("새 버전 푸쉬...");
222
+ await SdProcess.spawnAsync("git push");
223
+ await SdProcess.spawnAsync("git push --tags");
224
+ }
225
+
226
+ this._logger.debug("배포 시작...");
227
+ await pkgs.parallelAsync(async (pkg) => {
228
+ this._logger.debug(`[${pkg.name}] 배포를 시작합니다...`);
229
+ await pkg.publishAsync();
230
+ this._logger.debug(`[${pkg.name}] 배포가 완료되었습니다.`);
231
+ });
232
+ this._logger.info(`모든 배포가 완료되었습니다. (v${this._npmConfig.version})`);
233
+ }
234
+
204
235
  private async _runServerWorkerAsync(filePathOrOpt: string | { port: number }): Promise<{ worker: cp.ChildProcess; url: string }> {
205
236
  const workerPath = fileURLToPath(await import.meta.resolve!("../worker/server-worker"));
206
237
  return await new Promise<{ worker: cp.ChildProcess; url: string }>((resolve, reject) => {
@@ -285,17 +316,6 @@ export class SdCliWorkspace {
285
316
  serverInfo.url = serverWorkerInfo.url;
286
317
  await this._reloadServerWorkerPathProxyAsync(serverInfo);
287
318
 
288
- /*const serverMainPath = "file:///" + PathUtil.posix(entryFilePath) + "?update=" + Uuid.new().toString().replace(/-/g, "");
289
- const serverModule = await import(serverMainPath);
290
- serverInfo.server = serverModule.default as SdServiceServer | undefined;
291
- if (!serverInfo.server) {
292
- this._logger.error(`${entryFilePath}(0, 0): 'SdServiceServer'를 'export'해야 합니다.`);
293
- this._isServerRestarting = false;
294
- return;
295
- }
296
- serverInfo.server.devMiddlewares = serverInfo.middlewares;
297
- await Wait.until(() => serverInfo.server!.isOpen);*/
298
-
299
319
  this._logger.log(`[${pkg.name}] 서버가 시작되었습니다.`);
300
320
  }
301
321
  catch (err) {
@@ -305,20 +325,6 @@ export class SdCliWorkspace {
305
325
  this._isServerRestarting = false;
306
326
  }
307
327
 
308
- public async buildAsync(opt: { confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
309
- this._logger.debug("프로젝트 설정 가져오기...");
310
- const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
311
-
312
- this._logger.debug("패키지 목록 구성...");
313
- const pkgs = await this._getPackagesAsync(config, opt.pkgs);
314
-
315
- this._logger.debug("프로젝트 및 패키지 버전 설정...");
316
- await this._upgradeVersionAsync(pkgs);
317
-
318
- // 빌드
319
- await this._buildPkgsAsync(pkgs);
320
- }
321
-
322
328
  private async _buildPkgsAsync(pkgs: SdCliPackage[]): Promise<void> {
323
329
  this._logger.debug("빌드를 시작합니다...");
324
330
  const pkgNames = pkgs.map((item) => item.name);
@@ -349,60 +355,6 @@ export class SdCliWorkspace {
349
355
  }
350
356
  }
351
357
 
352
- public async publishAsync(opt: { noBuild: boolean; confFileRelPath: string; optNames: string[]; pkgs: string[] }): Promise<void> {
353
- this._logger.debug("프로젝트 설정 가져오기...");
354
- const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
355
-
356
- if (opt.noBuild) {
357
- this._logger.warn("빌드하지 않고, 배포하는것은 상당히 위험합니다.");
358
- await this._waitSecMessageAsync("프로세스를 중지하려면, 'CTRL+C'를 누르세요.", 5);
359
- }
360
-
361
- // GIT 사용중일 경우, 커밋되지 않은 수정사항이 있는지 확인
362
- if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
363
- this._logger.debug("GIT 커밋여부 확인...");
364
- const gitStatusResult = await SdProcess.spawnAsync("git status");
365
- if (gitStatusResult.includes("Changes") || gitStatusResult.includes("Untracked")) {
366
- throw new Error("커밋되지 않은 정보가 있습니다.\n" + gitStatusResult);
367
- }
368
- }
369
-
370
- this._logger.debug("패키지 목록 구성...");
371
- const pkgs = await this._getPackagesAsync(config, opt.pkgs);
372
-
373
- this._logger.debug("프로젝트 및 패키지 버전 설정...");
374
- await this._upgradeVersionAsync(pkgs);
375
-
376
- // 빌드
377
- if (!opt.noBuild) {
378
- // this._logger.debug("노드패키지 업데이트...");
379
- // await new SdCliNpm(this._rootPath).updateAsync();
380
-
381
- this._logger.debug("빌드를 시작합니다...");
382
- await this._buildPkgsAsync(pkgs);
383
- }
384
-
385
- // GIT 사용중일경우, 새 버전 커밋 및 TAG 생성
386
- if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
387
- this._logger.debug("새 버전 커밋 및 TAG 생성...");
388
- await SdProcess.spawnAsync("git add .");
389
- await SdProcess.spawnAsync(`git commit -m "v${this._npmConfig.version}"`);
390
- await SdProcess.spawnAsync(`git tag -a "v${this._npmConfig.version}" -m "v${this._npmConfig.version}"`);
391
-
392
- this._logger.debug("새 버전 푸쉬...");
393
- await SdProcess.spawnAsync("git push");
394
- await SdProcess.spawnAsync("git push --tags");
395
- }
396
-
397
- this._logger.debug("배포 시작...");
398
- await pkgs.parallelAsync(async (pkg) => {
399
- this._logger.debug(`[${pkg.name}] 배포를 시작합니다...`);
400
- await pkg.publishAsync();
401
- this._logger.debug(`[${pkg.name}] 배포가 완료되었습니다.`);
402
- });
403
- this._logger.info(`모든 배포가 완료되었습니다. (v${this._npmConfig.version})`);
404
- }
405
-
406
358
  private async _upgradeVersionAsync(pkgs: SdCliPackage[]): Promise<void> {
407
359
  // 작업공간 package.json 버전 설정
408
360
  const newVersion = semver.inc(this._npmConfig.version, "patch")!;
@@ -445,14 +397,14 @@ export class SdCliWorkspace {
445
397
  process.stdout.clearLine(0);
446
398
  }
447
399
 
448
- private async _getPackagesAsync(conf: ISdCliConfig, pkgs: string[]): Promise<SdCliPackage[]> {
400
+ private async _getPackagesAsync(conf: ISdCliConfig): Promise<SdCliPackage[]> {
449
401
  const pkgRootPaths = await this._npmConfig.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
450
402
  if (!pkgRootPaths) {
451
403
  throw new Error("최상위 'package.json'에서 'workspaces'를 찾을 수 없습니다.");
452
404
  }
453
405
 
454
406
  return pkgRootPaths.map((pkgRootPath) => {
455
- if (pkgs.length > 0 && !pkgs.includes(path.basename(pkgRootPath))) return undefined;
407
+ // if (pkgs.length > 0 && !pkgs.includes(path.basename(pkgRootPath))) return undefined;
456
408
  const pkgConfig = conf.packages[path.basename(pkgRootPath)];
457
409
  if (!pkgConfig) return undefined;
458
410
  return new SdCliPackage(this._rootPath, pkgRootPath, pkgConfig);
@@ -0,0 +1,30 @@
1
+ export const fc_package_eslintrc = (opt: { isForAngular: boolean }): string => /* language=cjs */ `
2
+
3
+ module.exports = {
4
+ overrides: [
5
+ {
6
+ files: ["*.ts"],
7
+ parserOptions: {
8
+ tsconfigRootDir: __dirname,
9
+ project: "tsconfig.json"
10
+ },
11
+ settings: {
12
+ "import/resolver": {
13
+ "typescript": {
14
+ project: require("path").resolve(__dirname, "tsconfig.json")
15
+ }
16
+ }
17
+ }
18
+ }${opt.isForAngular ? `,
19
+ {
20
+ files: ["*.ts"],
21
+ extends: ["plugin:@simplysm/angular"]
22
+ },
23
+ {
24
+ files: ["*.html"],
25
+ extends: ["plugin:@simplysm/angular-template"]
26
+ }` : ""}
27
+ ]
28
+ };
29
+
30
+ `.trim();