From bb0776caf1ef536deb01c3e17e3078b23daccc83 Mon Sep 17 00:00:00 2001
From: Evgeny Zakharov <risenforces@gmail.com>
Date: Mon, 15 Nov 2021 00:44:06 +0300
Subject: [PATCH] add build command

---
 package.json               |  2 +-
 src/actions/build.ts       | 43 +++++++++++++++++++++++++++++
 src/actions/start/index.ts |  1 +
 src/routes.tsx             | 56 ++++++++++++++++++++++++++++++++++++++
 src/ui/screens/build.tsx   |  4 +++
 5 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 src/actions/build.ts
 create mode 100644 src/ui/screens/build.tsx

diff --git a/package.json b/package.json
index 9aa53f3..c1a3274 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@medusa-frontends/cli",
-  "version": "1.0.1",
+  "version": "1.1.0",
   "description": "A CLI interface for bootstrapping and managing MFEs",
   "main": "bin/medusa.js",
   "repository": "git@github.com:mfe-playground/medusa-cli.git",
diff --git a/src/actions/build.ts b/src/actions/build.ts
new file mode 100644
index 0000000..ea480be
--- /dev/null
+++ b/src/actions/build.ts
@@ -0,0 +1,43 @@
+import 'zx/globals'
+import { readEnvironment } from '../configs/environment'
+import { foreachApp } from '../lib/apps/foreach'
+import { appHasScript, runAppScript } from '../lib/apps/scripts'
+import { readCLIConfig } from '../lib/config'
+import { EnvironmentNotFoundException } from '../lib/exceptions'
+import { showStatus } from '../model/status'
+import { AppMeta, ScriptKey } from '../types'
+import { generate } from './generate'
+
+type BuildOptions = {
+  buildScriptKey: ScriptKey
+  prebuildScriptKey: ScriptKey
+}
+
+export async function build({ buildScriptKey, prebuildScriptKey }: BuildOptions) {
+  await generate()
+
+  const { apps } = await readCLIConfig()
+
+  const buildApp = async ({ app }: AppMeta) => {
+    const environment = await readEnvironment(app)
+    if (!environment) throw new EnvironmentNotFoundException(app)
+
+    const { port } = environment
+
+    if (await appHasScript(app, prebuildScriptKey)) {
+      showStatus({ text: `Running prebuild for "${app}"..` })
+      const wrapped = await runAppScript(app, prebuildScriptKey)
+      await wrapped.processPromise()
+    }
+
+    showStatus({ text: `Building "${app}"..` })
+    const wrapped = await runAppScript(app, buildScriptKey, { port })
+    await wrapped.processPromise()
+  }
+
+  await foreachApp({
+    apps,
+    deep: true,
+    callback: buildApp,
+  })
+}
diff --git a/src/actions/start/index.ts b/src/actions/start/index.ts
index 81d89b0..4a4cde7 100644
--- a/src/actions/start/index.ts
+++ b/src/actions/start/index.ts
@@ -53,6 +53,7 @@ export async function start({ startScriptKey, prestartScriptKey }: StartOptions)
     const { port } = environment
 
     if (await appHasScript(app, prestartScriptKey)) {
+      appSummaryUpdated({ app, status: 'Running prestart..' })
       const wrapped = await runAppScript(app, prestartScriptKey)
       await wrapped.processPromise()
     }
diff --git a/src/routes.tsx b/src/routes.tsx
index 206ecbf..3635340 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -1,12 +1,14 @@
 import { program } from 'commander'
 import { useStore } from 'effector-react'
 import React from 'react'
+import { build } from './actions/build'
 import { generate } from './actions/generate'
 import { install } from './actions/install'
 import { pull } from './actions/pull'
 import { start } from './actions/start'
 import { $activeRoute, RouteConfig } from './model'
 import { BootstrapScreen } from './ui/screens/bootstrap'
+import { BuildScreen } from './ui/screens/build'
 import { GenerateScreen } from './ui/screens/generate'
 import { InstallScreen } from './ui/screens/install'
 import { PullScreen } from './ui/screens/pull'
@@ -41,6 +43,16 @@ export const routes: RouteConfig[] = [
         prestartScriptKey: 'prestart',
       }),
   },
+  {
+    name: 'start:dev',
+    command: program.command('start:dev'),
+    component: StartScreen,
+    action: () =>
+      start({
+        startScriptKey: 'start:dev',
+        prestartScriptKey: 'prestart:dev',
+      }),
+  },
   {
     name: 'start:prod',
     command: program.command('start:prod'),
@@ -51,6 +63,36 @@ export const routes: RouteConfig[] = [
         prestartScriptKey: 'prestart:prod',
       }),
   },
+  {
+    name: 'build',
+    command: program.command('build'),
+    component: BuildScreen,
+    action: () =>
+      build({
+        buildScriptKey: 'build',
+        prebuildScriptKey: 'prebuild',
+      }),
+  },
+  {
+    name: 'build:dev',
+    command: program.command('build:dev'),
+    component: BuildScreen,
+    action: () =>
+      build({
+        buildScriptKey: 'build:dev',
+        prebuildScriptKey: 'prebuild:dev',
+      }),
+  },
+  {
+    name: 'build:prod',
+    command: program.command('build:prod'),
+    component: BuildScreen,
+    action: () =>
+      build({
+        buildScriptKey: 'build:prod',
+        prebuildScriptKey: 'prebuild:prod',
+      }),
+  },
   {
     name: 'bootstrap',
     command: program.command('bootstrap'),
@@ -62,6 +104,20 @@ export const routes: RouteConfig[] = [
       await start({ startScriptKey: 'start', prestartScriptKey: 'prestart' })
     },
   },
+  {
+    name: 'bootstrap:dev',
+    command: program.command('bootstrap:dev'),
+    component: BootstrapScreen,
+    action: async () => {
+      await pull()
+      await install()
+      await generate()
+      await start({
+        startScriptKey: 'start:dev',
+        prestartScriptKey: 'prestart:dev',
+      })
+    },
+  },
   {
     name: 'bootstrap:prod',
     command: program.command('bootstrap:prod'),
diff --git a/src/ui/screens/build.tsx b/src/ui/screens/build.tsx
new file mode 100644
index 0000000..7d28969
--- /dev/null
+++ b/src/ui/screens/build.tsx
@@ -0,0 +1,4 @@
+import React from 'react'
+import { DefaultTemplate } from '../templates'
+
+export const BuildScreen = () => <DefaultTemplate />