@simplysm/sd-cli 7.0.100 → 7.0.151

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.
@@ -0,0 +1,111 @@
1
+ import https from "https";
2
+ import { SdProcess } from "@simplysm/sd-core-node";
3
+ import mime from "mime";
4
+
5
+ export class SdCliGithubApi {
6
+ public constructor(private readonly _apiKey: string,
7
+ private readonly _repoOwner: string,
8
+ private readonly _repoName: string) {
9
+ }
10
+
11
+ public async uploadAsync(version: string, files: { name: string; buffer: Buffer }[]): Promise<void> {
12
+ const releaseId = await this._createReleaseTagAsync(version);
13
+
14
+ for (const file of files) {
15
+ await this._uploadFileAsync(releaseId, file.name, file.buffer);
16
+ }
17
+ }
18
+
19
+ private async _uploadFileAsync(releaseId: number, fileName: string, buffer: Buffer): Promise<void> {
20
+ const contentLength = buffer.length;
21
+
22
+ await new Promise<void>((resolve, reject) => {
23
+ const req = https.request(
24
+ `https://uploads.github.com/repos/${this._repoOwner}/${this._repoName}/releases/${releaseId}/assets?name=${fileName}&label=${fileName}`,
25
+ {
26
+ method: "POST",
27
+ headers: {
28
+ "Authorization": `token ${this._apiKey}`,
29
+ "Accept": "application/vnd.github.v3+json",
30
+ "User-Agent": "@simplysm/sd-cli:publish",
31
+ "Content-Length": contentLength,
32
+ "Content-Type": mime.getType(fileName)!
33
+ }
34
+ },
35
+ (res) => {
36
+ let dataBuffer = Buffer.from([]);
37
+ res.on("data", data => {
38
+ dataBuffer = Buffer.concat([dataBuffer, data]);
39
+ });
40
+
41
+ res.on("end", () => {
42
+ if (res.statusCode !== 201) {
43
+ const errObj = JSON.parse(dataBuffer.toString());
44
+ throw new Error(errObj.message + "(" + errObj.documentation_url + ")");
45
+ }
46
+ else {
47
+ resolve();
48
+ }
49
+ });
50
+ }
51
+ );
52
+
53
+ req.on("error", (error) => {
54
+ reject(error);
55
+ });
56
+ req.write(buffer);
57
+ req.end();
58
+ });
59
+ }
60
+
61
+ private async _createReleaseTagAsync(ver: string): Promise<number> {
62
+ const currentBranch = (await SdProcess.spawnAsync("git branch --show-current")).trim();
63
+
64
+ return await new Promise<number>((resolve, reject) => {
65
+ const req = https.request(
66
+ `https://api.github.com/repos/${this._repoOwner}/${this._repoName}/releases`,
67
+ {
68
+ method: "POST",
69
+ headers: {
70
+ "Authorization": `token ${this._apiKey}`,
71
+ "Accept": "application/vnd.github.v3+json",
72
+ "User-Agent": "@simplysm/sd-cli:publish"
73
+ }
74
+ },
75
+ (res) => {
76
+ let dataBuffer = Buffer.from([]);
77
+ res.on("data", data => {
78
+ dataBuffer = Buffer.concat([dataBuffer, data]);
79
+ });
80
+
81
+ res.on("end", () => {
82
+ if (res.statusCode !== 201) {
83
+ const errObj = JSON.parse(dataBuffer.toString());
84
+ throw new Error(errObj.message + "(" + errObj.documentation_url + ")");
85
+ }
86
+ else {
87
+ // console.log(JSON.parse(dataBuffer.toString()));
88
+ const resData = JSON.parse(dataBuffer.toString());
89
+ resolve(resData.id);
90
+ }
91
+ });
92
+ }
93
+ );
94
+
95
+ req.on("error", (error) => {
96
+ reject(error);
97
+ });
98
+
99
+ req.write(JSON.stringify({
100
+ tag_name: `v${ver}`,
101
+ target_commitish: currentBranch,
102
+ name: `v${ver}`,
103
+ body: `v${ver}`,
104
+ draft: false,
105
+ prerelease: false
106
+ }));
107
+
108
+ req.end();
109
+ });
110
+ }
111
+ }
@@ -7,7 +7,6 @@ import ts from "typescript";
7
7
  import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
8
8
  import { NamedChunksPlugin } from "@angular-devkit/build-angular/src/webpack/plugins/named-chunks-plugin";
9
9
  import {
10
- CommonJsUsageWarnPlugin,
11
10
  DedupeModuleResolvePlugin,
12
11
  JavaScriptOptimizerPlugin,
13
12
  SuppressExtractedTextChunksWebpackPlugin
@@ -35,7 +34,6 @@ import { SdCliNgModuleGenerator } from "../ng-tools/SdCliNgModuleGenerator";
35
34
  import { SdCliCordova } from "../build-tool/SdCliCordova";
36
35
  import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
37
36
  import electronBuilder from "electron-builder";
38
- import { NeverEntryError } from "@simplysm/sd-core-common";
39
37
  import LintResult = ESLint.LintResult;
40
38
 
41
39
  export class SdCliClientBuilder extends EventEmitter {
@@ -85,8 +83,8 @@ export class SdCliClientBuilder extends EventEmitter {
85
83
  } : undefined);
86
84
 
87
85
  // CORDOVA
88
- if (this._config.builders?.cordova) {
89
- this._cordova = new SdCliCordova(this._rootPath, this._config.builders.cordova);
86
+ if (this._config.builder?.cordova) {
87
+ this._cordova = new SdCliCordova(this._rootPath, this._config.builder.cordova);
90
88
  }
91
89
  }
92
90
 
@@ -111,7 +109,7 @@ export class SdCliClientBuilder extends EventEmitter {
111
109
  }
112
110
 
113
111
  // 빌드 준비
114
- const webpackConfigs = (Object.keys(this._config.builders ?? { web: {} }) as ("web" | "cordova" | "electron")[])
112
+ const webpackConfigs = (Object.keys(this._config.builder ?? { web: {} }) as ("web" | "cordova" | "electron")[])
115
113
  .map((builderType) => this._getWebpackConfig(true, builderType));
116
114
  const multiCompiler = webpack(webpackConfigs);
117
115
  return await new Promise<NextHandleFunction[]>((resolve, reject) => {
@@ -193,7 +191,7 @@ export class SdCliClientBuilder extends EventEmitter {
193
191
 
194
192
  // 빌드
195
193
  this._logger.debug("Webpack 빌드 수행...");
196
- const builderTypes = (Object.keys(this._config.builders ?? { web: {} }) as ("web" | "cordova" | "electron")[]);
194
+ const builderTypes = (Object.keys(this._config.builder ?? { web: {} }) as ("web" | "cordova" | "electron")[]);
197
195
  const webpackConfigs = builderTypes.map((builderType) => this._getWebpackConfig(false, builderType));
198
196
  const multipleCompiler = webpack(webpackConfigs);
199
197
  const buildResults = await new Promise<ISdCliPackageBuildResult[]>((resolve, reject) => {
@@ -218,8 +216,8 @@ export class SdCliClientBuilder extends EventEmitter {
218
216
  const packageKey = this._getNpmConfig(this._rootPath)!.name.split("/").last()!;
219
217
  await augmentAppWithServiceWorker(
220
218
  PathUtil.posix(path.relative(this._workspaceRootPath, this._rootPath)) as any,
221
- PathUtil.posix(path.relative(this._workspaceRootPath, path.resolve(this._parsedTsconfig.options.outDir!, "web"))) as any,
222
- `/${packageKey}/web/`,
219
+ PathUtil.posix(path.relative(this._workspaceRootPath, path.resolve(this._parsedTsconfig.options.outDir!))) as any,
220
+ `/${packageKey}/`,
223
221
  PathUtil.posix(path.relative(this._workspaceRootPath, path.resolve(this._rootPath, "ngsw-config.json")))
224
222
  );
225
223
  }
@@ -234,14 +232,23 @@ export class SdCliClientBuilder extends EventEmitter {
234
232
  }
235
233
 
236
234
  // ELECTRON
237
- if (this._config.builders?.electron) {
235
+ if (this._config.builder?.electron) {
238
236
  const npmConfig = this._getNpmConfig(this._rootPath)!;
239
237
 
240
- if (npmConfig.dependencies?.["electron"] == null) {
241
- throw new NeverEntryError();
238
+ const electronVersion = npmConfig.dependencies?.["electron"];
239
+ if (electronVersion === undefined) {
240
+ throw new Error("ELECTRON 빌드 패키지의 'dependencies'에는 'electron'이 반드시 포함되어야 합니다.");
242
241
  }
243
242
 
244
- await FsUtil.writeJsonAsync(path.resolve(this._rootPath, `.electron/src/package.json`), {
243
+ const dotenvVersion = npmConfig.dependencies?.["dotenv"];
244
+ if (dotenvVersion === undefined) {
245
+ throw new Error("ELECTRON 빌드 패키지의 'dependencies'에는 'dotenv'가 반드시 포함되어야 합니다.");
246
+ }
247
+
248
+ const electronSrcPath = path.resolve(this._rootPath, `.electron/src`);
249
+ const electronDistPath = path.resolve(this._rootPath, `.electron/dist`);
250
+
251
+ await FsUtil.writeJsonAsync(path.resolve(electronSrcPath, `package.json`), {
245
252
  name: npmConfig.name,
246
253
  version: npmConfig.version,
247
254
  description: npmConfig.description,
@@ -249,24 +256,34 @@ export class SdCliClientBuilder extends EventEmitter {
249
256
  author: npmConfig.author,
250
257
  license: npmConfig.license,
251
258
  devDependencies: {
252
- "electron": npmConfig.dependencies["electron"].replace("^", "")
259
+ "electron": electronVersion.replace("^", "")
260
+ },
261
+ dependencies: {
262
+ "dotenv": dotenvVersion
253
263
  }
254
264
  });
255
265
 
256
- await FsUtil.writeFileAsync(path.resolve(this._rootPath, `.electron/src/.env`), `NODE_ENV=production`);
266
+ await FsUtil.writeFileAsync(path.resolve(electronSrcPath, `.env`), [
267
+ "NODE_ENV=production",
268
+ `SD_VERSION=${npmConfig.version}`,
269
+ (this._config.builder.electron.icon !== undefined) ? `SD_ELECTRON_ICON=${this._config.builder.electron.icon}` : `SD_ELECTRON_ICON=favicon.ico`,
270
+ ...(this._config.env !== undefined) ? Object.keys(this._config.env).map((key) => `${key}=${this._config.env![key]}`) : []
271
+ ].filterExists().join("\n"));
257
272
 
258
- await FsUtil.copyAsync(path.resolve(this._rootPath, `src/electron.prod.js`), path.resolve(this._rootPath, ".electron/src/electron.js"));
273
+ let electronTsFileContent = await FsUtil.readFileAsync(path.resolve(this._rootPath, `src/electron.ts`));
274
+ electronTsFileContent = "require(\"dotenv\").config({ path: `${__dirname}\\\\.env` });\n" + electronTsFileContent;
275
+ const result = ts.transpileModule(electronTsFileContent, { compilerOptions: { module: ts.ModuleKind.CommonJS } });
276
+ await FsUtil.writeFileAsync(path.resolve(electronSrcPath, "electron.js"), result.outputText);
259
277
 
260
278
  await electronBuilder.build({
261
279
  targets: electronBuilder.Platform.WINDOWS.createTarget(),
262
280
  config: {
263
- appId: this._config.builders.electron.appId,
281
+ appId: this._config.builder.electron.appId,
264
282
  productName: npmConfig.description,
265
- asar: true,
266
283
  nsis: {},
267
284
  directories: {
268
- app: path.resolve(this._rootPath, ".electron/src"),
269
- output: path.resolve(this._rootPath, ".electron/dist")
285
+ app: electronSrcPath,
286
+ output: electronDistPath
270
287
  }
271
288
  }
272
289
  });
@@ -300,20 +317,21 @@ export class SdCliClientBuilder extends EventEmitter {
300
317
  const internalModuleCachePaths = watch ? this._getInternalModuleCachePaths(workspaceName) : undefined;
301
318
 
302
319
  const npmConfig = this._getNpmConfig(this._rootPath)!;
303
- const pkgVersion = npmConfig.version;
304
- const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
320
+ // const pkgVersion = npmConfig.version;
321
+ // const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
322
+
323
+ const workspacePkgLockContent = FsUtil.readFile(path.resolve(this._workspaceRootPath, "package-lock.json"));
305
324
 
306
325
  const pkgKey = npmConfig.name.split("/").last()!;
307
- const publicPath = (builderType === "web" || watch) ? `/${pkgKey}/${builderType}/` : ``;
326
+ const publicPath = builderType === "web" ? `/${pkgKey}/` : watch ? `/${pkgKey}/${builderType}/` : ``;
308
327
 
309
328
  const cacheBasePath = path.resolve(this._rootPath, ".cache");
310
- const cachePath = path.resolve(cacheBasePath, pkgVersion);
329
+ // const cachePath = path.resolve(cacheBasePath, pkgVersion);
311
330
 
312
- const distPath = (builderType === "cordova" && !watch)
313
- ? path.resolve(this._cordova!.cordovaPath, "www")
314
- : (builderType === "electron" && !watch)
315
- ? path.resolve(this._rootPath, ".electron/src")
316
- : `${this._parsedTsconfig.options.outDir}/${builderType}`;
331
+ const distPath = (builderType === "cordova" && !watch) ? path.resolve(this._cordova!.cordovaPath, "www")
332
+ : (builderType === "electron" && !watch) ? path.resolve(this._rootPath, ".electron/src")
333
+ : builderType === "web" ? this._parsedTsconfig.options.outDir
334
+ : `${this._parsedTsconfig.options.outDir}/${builderType}`;
317
335
 
318
336
  const sassImplementation = new SassWorkerImplementation();
319
337
 
@@ -376,14 +394,15 @@ export class SdCliClientBuilder extends EventEmitter {
376
394
  cache: {
377
395
  type: "filesystem",
378
396
  profile: watch ? undefined : false,
379
- cacheDirectory: path.resolve(cachePath, "angular-webpack"),
397
+ cacheDirectory: path.resolve(cacheBasePath, "angular-webpack"),
380
398
  maxMemoryGenerations: 1,
381
399
  name: createHash("sha1")
382
- .update(pkgVersion)
383
- .update(ngVersion)
400
+ .update(workspacePkgLockContent)
401
+ // .update(pkgVersion)
402
+ // .update(ngVersion)
384
403
  .update(JSON.stringify(this._parsedTsconfig.options))
385
- .update(this._workspaceRootPath)
386
- .update(this._rootPath)
404
+ // .update(this._workspaceRootPath)
405
+ // .update(this._rootPath)
387
406
  .update(JSON.stringify(this._config))
388
407
  .update(watch.toString())
389
408
  .digest("hex")
@@ -490,7 +509,7 @@ export class SdCliClientBuilder extends EventEmitter {
490
509
  {
491
510
  loader: "@angular-devkit/build-angular/src/babel/webpack-loader",
492
511
  options: {
493
- cacheDirectory: path.resolve(cachePath, "babel-webpack"),
512
+ cacheDirectory: path.resolve(cacheBasePath, "babel-webpack"),
494
513
  scriptTarget: ts.ScriptTarget.ES2017,
495
514
  aot: true,
496
515
  optimize: !watch,
@@ -564,7 +583,9 @@ export class SdCliClientBuilder extends EventEmitter {
564
583
  ]
565
584
  },
566
585
  plugins: [
567
- new NodePolyfillPlugin(),
586
+ new NodePolyfillPlugin({
587
+ excludeAliases: builderType === "electron" ? ["process"] : []
588
+ }),
568
589
  new NamedChunksPlugin(),
569
590
  new DedupeModuleResolvePlugin(),
570
591
  new webpack.ProgressPlugin({
@@ -578,9 +599,6 @@ export class SdCliClientBuilder extends EventEmitter {
578
599
  }
579
600
  }
580
601
  }),
581
- new CommonJsUsageWarnPlugin({
582
- allowedDependencies: ["@fortawesome"]
583
- }),
584
602
  ...watch ? [] : [
585
603
  new LicenseWebpackPlugin({
586
604
  stats: { warnings: false, errors: false },
@@ -612,18 +630,18 @@ export class SdCliClientBuilder extends EventEmitter {
612
630
  {
613
631
  context: this._cordova!.cordovaPath,
614
632
  to: `cordova-${platform}/plugins`,
615
- from: `platforms/${platform}/www/plugins`,
633
+ from: `platforms/${platform}/platform_www/plugins`,
616
634
  noErrorOnMissing: true
617
635
  },
618
636
  {
619
637
  context: this._cordova!.cordovaPath,
620
638
  to: `cordova-${platform}/cordova.js`,
621
- from: `platforms/${platform}/www/cordova.js`
639
+ from: `platforms/${platform}/platform_www/cordova.js`
622
640
  },
623
641
  {
624
642
  context: this._cordova!.cordovaPath,
625
643
  to: `cordova-${platform}/cordova_plugins.js`,
626
- from: `platforms/${platform}/www/cordova_plugins.js`,
644
+ from: `platforms/${platform}/platform_www/cordova_plugins.js`,
627
645
  noErrorOnMissing: true
628
646
  },
629
647
  {
@@ -685,7 +703,7 @@ export class SdCliClientBuilder extends EventEmitter {
685
703
  cache: {
686
704
  enabled: true,
687
705
  basePath: cacheBasePath,
688
- path: cachePath
706
+ path: path.resolve(cacheBasePath, "index-webpack")
689
707
  },
690
708
  postTransform: undefined,
691
709
  optimization: {
@@ -187,11 +187,12 @@ export class SdCliServerBuilder extends EventEmitter {
187
187
 
188
188
  const npmConfig = this._getNpmConfig(this._rootPath)!;
189
189
  const pkgKey = npmConfig.name.split("/").last()!;
190
- const pkgVersion = npmConfig.version;
190
+ // const pkgVersion = npmConfig.version;
191
191
 
192
- const cacheBasePath = path.resolve(this._rootPath, ".cache");
193
- const cachePath = path.resolve(cacheBasePath, pkgVersion);
192
+ const workspacePkgLockContent = FsUtil.readFile(path.resolve(this._workspaceRootPath, "package-lock.json"));
194
193
 
194
+ const cacheBasePath = path.resolve(this._rootPath, ".cache");
195
+ // const cachePath = path.resolve(cacheBasePath, pkgVersion);
195
196
 
196
197
  let prevProgressMessage = "";
197
198
  return {
@@ -241,13 +242,11 @@ export class SdCliServerBuilder extends EventEmitter {
241
242
  cache: {
242
243
  type: "filesystem",
243
244
  profile: watch ? undefined : false,
244
- cacheDirectory: path.resolve(cachePath, "server-webpack"),
245
+ cacheDirectory: path.resolve(cacheBasePath, "server-webpack"),
245
246
  maxMemoryGenerations: 1,
246
247
  name: createHash("sha1")
247
- .update(pkgVersion)
248
+ .update(workspacePkgLockContent)
248
249
  .update(JSON.stringify(this._parsedTsconfig.options))
249
- .update(this._workspaceRootPath)
250
- .update(this._rootPath)
251
250
  .update(JSON.stringify(this._config))
252
251
  .update(watch.toString())
253
252
  .digest("hex")
package/src/commons.ts CHANGED
@@ -4,6 +4,11 @@ export interface INpmConfig {
4
4
  description?: string;
5
5
  author?: string;
6
6
  license?: string;
7
+ repository: string | {
8
+ type: string;
9
+ url: string;
10
+ directory?: string;
11
+ };
7
12
  type?: "module";
8
13
  workspaces?: string[];
9
14
  main?: string;
@@ -66,7 +71,7 @@ export interface ISdCliServerPackageConfig {
66
71
 
67
72
  export interface ISdCliClientPackageConfig {
68
73
  type: "client";
69
- builders?: {
74
+ builder?: {
70
75
  web?: ISdCliClientBuilderWebConfig;
71
76
  cordova?: ISdCliClientBuilderCordovaConfig;
72
77
  electron?: ISdCliClientBuilderElectronConfig;
@@ -77,7 +82,7 @@ export interface ISdCliClientPackageConfig {
77
82
  publish?: TSdCliPublishConfig;
78
83
  }
79
84
 
80
- export type TSdCliPublishConfig = ISdCliFtpPublishConfig | ISdCliLocalDirectoryPublishConfig;
85
+ export type TSdCliPublishConfig = ISdCliFtpPublishConfig | ISdCliLocalDirectoryPublishConfig | ISdCliGithubPublishConfig;
81
86
 
82
87
  export interface ISdCliFtpPublishConfig {
83
88
  type: "ftp" | "ftps" | "sftp";
@@ -93,17 +98,22 @@ export interface ISdCliLocalDirectoryPublishConfig {
93
98
  path: string;
94
99
  }
95
100
 
101
+ export interface ISdCliGithubPublishConfig {
102
+ type: "github";
103
+ apiKey: string;
104
+ files: { from: string; to: string }[];
105
+ }
106
+
96
107
  export interface ISdCliClientBuilderWebConfig {
97
108
  }
98
109
 
99
110
  export interface ISdCliClientBuilderCordovaConfig {
100
- type: "cordova";
101
111
  appId: string;
102
112
  appName: string;
103
113
  plugins?: string[];
104
114
  icon?: string;
105
115
  debug?: boolean;
106
- targets?: {
116
+ target?: {
107
117
  browser?: {};
108
118
  android?: {
109
119
  bundle?: boolean;
@@ -120,9 +130,5 @@ export interface ISdCliClientBuilderCordovaConfig {
120
130
 
121
131
  export interface ISdCliClientBuilderElectronConfig {
122
132
  appId: string;
123
- }
124
-
125
- export type TSdCliClientBuilderConfig =
126
- ISdCliClientBuilderWebConfig
127
- | ISdCliClientBuilderCordovaConfig
128
- | ISdCliClientBuilderElectronConfig;
133
+ icon?: string;
134
+ }
@@ -83,7 +83,11 @@ export class SdCliWorkspace {
83
83
  if (typeof pkg.config.server === "string") {
84
84
  const serverInfo = this._serverInfoMap.getOrCreate(pkg.config.server, { middlewares: [], clientInfos: [] });
85
85
  serverInfo.middlewares.push(...middlewares);
86
- serverInfo.clientInfos.push({ pkgKey: pkg.name.split("/").last()! });
86
+ serverInfo.clientInfos.push({
87
+ pkgKey: pkg.name.split("/").last()!,
88
+ platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
89
+ cordovaTargets: pkg.config.builder?.cordova?.target ? Object.keys(pkg.config.builder.cordova.target) : ["browser"]
90
+ });
87
91
  }
88
92
  else { // DEV SERVER
89
93
  const serverInfo = this._serverInfoMap.getOrCreate("_", { middlewares: [], clientInfos: [] });
@@ -96,7 +100,11 @@ export class SdCliWorkspace {
96
100
  await server.listenAsync();
97
101
  serverInfo.server = server;
98
102
  serverInfo.server.devMiddlewares = middlewares;
99
- serverInfo.clientInfos.push({ pkgKey: pkg.name.split("/").last()! });
103
+ serverInfo.clientInfos.push({
104
+ pkgKey: pkg.name.split("/").last()!,
105
+ platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
106
+ cordovaTargets: pkg.config.builder?.cordova?.target ? Object.keys(pkg.config.builder.cordova.target) : ["browser"]
107
+ });
100
108
  }
101
109
  }
102
110
  }
@@ -250,6 +258,9 @@ export class SdCliWorkspace {
250
258
  await SdProcess.spawnAsync("git add .");
251
259
  await SdProcess.spawnAsync(`git commit -m "v${this._npmConfig.version}"`);
252
260
  await SdProcess.spawnAsync(`git tag -a "v${this._npmConfig.version}" -m "v${this._npmConfig.version}"`);
261
+
262
+ this._logger.debug("새 버전 푸쉬...");
263
+ await SdProcess.spawnAsync("git push --tags");
253
264
  }
254
265
 
255
266
  this._logger.debug("배포 시작...");
@@ -361,11 +372,28 @@ export class SdCliWorkspace {
361
372
  const portStr = serverInfo.server.options.port.toString();
362
373
 
363
374
  for (const clientInfo of serverInfo.clientInfos) {
364
- clientHrefs.push(`${protocolStr}://localhost:${portStr}/${clientInfo.pkgKey}/`);
375
+ for (const platform of clientInfo.platforms) {
376
+ if (platform === "web") {
377
+ clientHrefs.push(`${protocolStr}://localhost:${portStr}/${clientInfo.pkgKey}/`);
378
+ }
379
+ else if (platform === "electron") {
380
+ clientHrefs.push(`sd-cli run-electron ${clientInfo.pkgKey} http://localhost:${portStr}`);
381
+ }
382
+ else if (platform === "cordova") {
383
+ for (const target of clientInfo.cordovaTargets) {
384
+ if (target === "browser") {
385
+ clientHrefs.push(`${protocolStr}://localhost:${portStr}/${clientInfo.pkgKey}/${platform}/`);
386
+ }
387
+ else {
388
+ clientHrefs.push(`sd-cli run-cordova ${clientInfo.pkgKey} http://[IP]:${portStr}`);
389
+ }
390
+ }
391
+ }
392
+ }
365
393
  }
366
394
  }
367
395
  if (clientHrefs.length > 0) {
368
- this._logger.log(`오픈된 클라이언트: ${clientHrefs.join(", ")}`);
396
+ this._logger.log(`오픈된 클라이언트:\n${clientHrefs.join("\n")}`);
369
397
  }
370
398
  }
371
399
  }
@@ -373,5 +401,5 @@ export class SdCliWorkspace {
373
401
  interface IServerInfo {
374
402
  server?: SdServiceServer;
375
403
  middlewares: NextHandleFunction[];
376
- clientInfos: { pkgKey: string }[];
404
+ clientInfos: { pkgKey: string; platforms: string[]; cordovaTargets: string[] }[];
377
405
  }
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./build-tool/SdCliCacheCompilerHost";
2
2
  export * from "./build-tool/SdCliCordova";
3
3
  export * from "./build-tool/SdCliElectron";
4
+ export * from "./build-tool/SdCliGithubApi";
4
5
  export * from "./build-tool/SdCliIndexFileGenerator";
5
6
  export * from "./build-tool/SdCliNgCacheCompilerHost";
6
7
  export * from "./build-tool/SdCliPackageLinter";
@@ -11,6 +11,7 @@ import { SdCliClientBuilder } from "../builder/SdCliClientBuilder";
11
11
  import { NextHandleFunction } from "connect";
12
12
  import { SdStorage } from "@simplysm/sd-storage";
13
13
  import ts from "typescript";
14
+ import { SdCliGithubApi } from "../build-tool/SdCliGithubApi";
14
15
 
15
16
  export class SdCliPackage extends EventEmitter {
16
17
  private readonly _npmConfig: INpmConfig;
@@ -96,7 +97,23 @@ export class SdCliPackage extends EventEmitter {
96
97
  }
97
98
  }
98
99
  else {
99
- if (this.config.publish.type === "ftp" || this.config.publish.type === "ftps" || this.config.publish.type === "sftp") {
100
+ if (this.config.publish.type === "github") {
101
+ const repoUrl = typeof this._npmConfig.repository === "string" ? this._npmConfig.repository : this._npmConfig.repository.url;
102
+ const repoOwner = repoUrl.split("/").slice(-2)[0];
103
+ const repoName = repoUrl.split("/").slice(-2)[1].replace(/\..*/g, "");
104
+
105
+ const github = new SdCliGithubApi(
106
+ this.config.publish.apiKey,
107
+ repoOwner,
108
+ repoName
109
+ );
110
+
111
+ await github.uploadAsync(this._npmConfig.version, this.config.publish.files.map((item) => ({
112
+ buffer: FsUtil.readFileBuffer(path.resolve(this.rootPath, "dist", item.from)),
113
+ name: item.to
114
+ })));
115
+ }
116
+ else if (this.config.publish.type === "ftp" || this.config.publish.type === "ftps" || this.config.publish.type === "sftp") {
100
117
  const tsconfigPath = path.resolve(this.rootPath, "tsconfig-build.json");
101
118
  const tsconfig = FsUtil.readJson(tsconfigPath);
102
119
  const parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this.rootPath, tsconfig.angularCompilerOptions);