eitri-cli 1.6.1 → 1.7.0-beta.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eitri-cli",
3
- "version": "1.6.1",
3
+ "version": "1.7.0-beta.1",
4
4
  "description": "Command Line Interface to make \"Eitri-App\" with code and fire.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -0,0 +1,103 @@
1
+ const util = require('util');
2
+ const inquirer = require("inquirer");
3
+ const GenericUtils = require('../../util/GenericUtils');
4
+ const exec = util.promisify(require("child_process").exec)
5
+
6
+ module.exports = class AndroidEmulatorService {
7
+
8
+ static async open(deepLink, shareId) {
9
+ await this.checkHasInstalledAdb()
10
+ const serialNumber = await this.selectDevice()
11
+ const cmd = `adb -s ${serialNumber} shell am start -a android.intent.action.VIEW -d ${deepLink}/${shareId}`
12
+ const opened = await this.openDeepLink(cmd)
13
+ if (opened) return;
14
+ }
15
+
16
+ static async checkHasInstalledAdb() {
17
+ try {
18
+ console.log("Verificando instalação do ABD",)
19
+ const command = "adb --version"
20
+ await exec(command)
21
+ console.log("ADB Instalado. Continuando...")
22
+ } catch (error) {
23
+ throw new Error('"adb" não instalado. Saiba mais em https://developer.android.com/tools/adb')
24
+ }
25
+ }
26
+
27
+ static async selectDevice() {
28
+ const devices = await this.checkAttachedDevices()
29
+
30
+ if (devices.length === 0) {
31
+ throw new Error('Dipositivo não selecionado')
32
+ }
33
+
34
+ if (devices.length === 1) {
35
+ return GenericUtils.getSerialNumberFromAdb(devices[0])
36
+ }
37
+
38
+ const res = await inquirer.prompt([
39
+ {
40
+ name: "accepted",
41
+ type: "list",
42
+ message:
43
+ "Selecione o Android que deseja se conectar",
44
+ choices: devices,
45
+ pageSize: devices.length + 2,
46
+ },
47
+ ]);
48
+
49
+ if (res.accepted && typeof res.accepted === "string") {
50
+ console.log("Dispositivo selecionado: ", res.accepted, "\n")
51
+ return GenericUtils.getSerialNumberFromAdb(res.accepted)
52
+ }
53
+
54
+ }
55
+
56
+ static async checkAttachedDevices() {
57
+ console.log("Verificando dispositivos ADB conectados")
58
+ const devices = await this.getListAdbDevices()
59
+ if (!devices.length) {
60
+ throw new Error('Nenhum dispositivo/emulador encontrado')
61
+ }
62
+
63
+ return devices
64
+ }
65
+
66
+ static async openDeepLink(cmd) {
67
+ try {
68
+ const {stderr} = await exec(cmd)
69
+ return !(stderr);
70
+ } catch (error) {
71
+ console.log(`Houve um erro ao tentar abrir o Eitri-App via deep link`)
72
+ console.log(error)
73
+ return process.exit(1)
74
+ }
75
+ }
76
+
77
+ static async getListAdbDevices() {
78
+
79
+ return new Promise((resolve, _reject) => {
80
+ exec('adb devices -l', (error, stdout, _stderr) => {
81
+ const adbDevices = []
82
+ if (error) {
83
+ console.error(`Erro ao executar o comando: ${error}`);
84
+ return;
85
+ }
86
+
87
+ const devicesList = stdout.split('\n');
88
+ const devices = devicesList.slice(1, -2);
89
+
90
+ devices.forEach(device => {
91
+ adbDevices.push(device)
92
+ });
93
+ resolve(adbDevices)
94
+ });
95
+
96
+ })
97
+ }
98
+
99
+
100
+
101
+ }
102
+
103
+
@@ -0,0 +1,70 @@
1
+ const util = require('util');
2
+ const exec = util.promisify(require("child_process").exec)
3
+
4
+ module.exports = class IOSEmulatorService {
5
+
6
+ static async open(deepLink, shareId) {
7
+ await this.checkHasInstalledXcode()
8
+
9
+ const cmd = `xcrun simctl openurl booted ${deepLink}/${shareId}`
10
+ const opened = await this.openDeepLink(cmd)
11
+ if (opened) return;
12
+
13
+ }
14
+
15
+ static async openDeepLink(cmd) {
16
+ try {
17
+ const {stderr} = await exec(cmd)
18
+ return !(stderr);
19
+ } catch (error) {
20
+ console.log(`Houve um erro ao tentar abrir o Eitri-App via deep link`)
21
+ console.log(error)
22
+ return process.exit(1)
23
+ }
24
+ }
25
+
26
+ static async checkHasInstalledXcode(){
27
+ try {
28
+ console.log("Verificando instalação do Xcode.")
29
+ const command = "xcode-select -p"
30
+ await exec(command)
31
+ console.log("Xcode instalado")
32
+ } catch (error) {
33
+ throw new Error('"Xcode" não encontrado. Saiba mais em https://developer.apple.com/xcode/')
34
+ }
35
+ }
36
+
37
+ /**
38
+ * TODO implementar seleção de iPhone
39
+ */
40
+ static async selectDevice(){
41
+ const devices = this.getListIphones()
42
+ const res = await inquirer.prompt([
43
+ {
44
+ name: "accepted",
45
+ type: "list",
46
+ message:
47
+ "Selecione o iPhone que deseja se conectar",
48
+ choices: devices,
49
+ pageSize: devices.length + 2,
50
+ },
51
+ ]);
52
+
53
+ if (res.accepted && typeof res.accepted === "string") {
54
+ console.log("iPhone selecionado: ", res.accepted, "\n")
55
+ return GenericUtils.getSerialNumberFromAdb(res.accepted)
56
+ }
57
+
58
+ }
59
+ /**
60
+ * TODO implementar lista de iPhones
61
+ */
62
+ static async getListIphones(){
63
+ console.log("Verificando dispositivos Apple conectados")
64
+ const command = 'xcrun simctl list devices | grep -i "iphone"'
65
+ await exec(command)
66
+ }
67
+
68
+ }
69
+
70
+
@@ -0,0 +1,20 @@
1
+ const AndroidEmulatorService = require('./Emulator/AndroidEmulatorService');
2
+ const IOSEmulatorService = require('./Emulator/IOSEmulatorService');
3
+
4
+ module.exports = class EmulatorService {
5
+
6
+ static async openSimulator(emulator, shareId, deepLinks) {
7
+ try {
8
+ const emulatorService = emulator === "ios" ? IOSEmulatorService : AndroidEmulatorService;
9
+
10
+ for (const deepLink of deepLinks) {
11
+ await emulatorService.open(deepLink, shareId)
12
+ }
13
+ } catch (error) {
14
+ throw {message: error.message}
15
+ }
16
+ }
17
+
18
+ }
19
+
20
+
@@ -24,6 +24,7 @@ module.exports = class HuginService {
24
24
  formData.append("filepath", relativePath);
25
25
  formData.append("isDevMode", String(isDevMode));
26
26
  formData.append("eitriAppId", eitriConf.id);
27
+ formData.append("applicationId", eitriConf.applicationId);
27
28
  formData.append("workspaceId", workspace.id);
28
29
  let url = this.getServerlessUploadUrl(filePath);
29
30
  await this.http.postForm(url, formData);
@@ -1,20 +1,20 @@
1
1
  const configService = require('./ConfigService')
2
2
  const targetEnum = require('../enum/target')
3
3
  // eslint-disable-next-line no-unused-vars
4
-
5
- const LIBS_FOR_TARGET = {
6
- MOBILE: {
7
- superApp: 'eitri-app-client',
8
- components: 'eitri-app-components',
9
- sdkSupport: 'eitri-app-sdk-support',
10
- },
11
- WEB: {
12
- superApp: 'eitri-app-client-web',
13
- components: 'eitri-miniapp-components-web',
14
- sdkSupport: 'eitri-app-sdk-support',
15
- },
16
- }
17
4
  class TargetService{
5
+
6
+ static LIBS_FOR_TARGET = {
7
+ MOBILE: {
8
+ bifrost: 'eitri-app-client',
9
+ luminus: 'eitri-app-components',
10
+ sdkSupport: 'eitri-app-sdk-support',
11
+ },
12
+ MOBILE_NEW: {
13
+ bifrost: 'eitri-bifrost',
14
+ luminus: 'eitri-luminus',
15
+ sdkSupport: 'eitri-app-sdk-support',
16
+ },
17
+ }
18
18
  constructor(workspace) {
19
19
  this.workspace = workspace
20
20
  this.conf = configService.get('managerApi')
@@ -37,16 +37,16 @@ class TargetService{
37
37
  }
38
38
  }
39
39
 
40
- static getLibsFromMiniConf(miniConf, availableTargets) {
41
- const target = availableTargets.find(t => t.name === miniConf.target)
42
- if (target) {
40
+ static getLibsFromMiniConf(eitriConf, availableTargets) {
41
+ const application = availableTargets.find(t => t.name === eitriConf.target || t.id === eitriConf.applicationId)
42
+ if (application) {
43
43
  return {
44
- superApp: target.superAppClientLibName,
45
- components: target.componentsLibName,
46
- sdkSupport: target.sdkSupportLibName || LIBS_FOR_TARGET.MOBILE.sdkSupport
44
+ bifrost: application.superAppClientLibName,
45
+ luminus: application.componentsLibName,
46
+ sdkSupport: application.sdkSupportLibName || this.LIBS_FOR_TARGET.MOBILE.sdkSupport
47
47
  }
48
48
  }
49
- return LIBS_FOR_TARGET.MOBILE
49
+ return this.LIBS_FOR_TARGET.MOBILE
50
50
  }
51
51
 
52
52
  async getLibs() {
@@ -28,6 +28,7 @@ const EitriAppService = require("./EitriAppService");
28
28
  const VegvisirService = require("../modules/vegvisir/VegvisirService");
29
29
  const HuginService = require("./HuginService");
30
30
  const EitriAppType = require("../model/EitriAppType");
31
+ const chalk = require("chalk");
31
32
  const vegvisirService = new VegvisirService()
32
33
  const huginService = new HuginService()
33
34
 
@@ -286,7 +287,7 @@ class Workspace {
286
287
 
287
288
  async checkVersions() {
288
289
  try {
289
- const miniConf = this.getMiniConf();
290
+ const eitriConf = this.getMiniConf();
290
291
  const headers = {
291
292
  accept: this.config.libs.updateLibsEndpointVersion,
292
293
  };
@@ -294,25 +295,33 @@ class Workspace {
294
295
  // somente para garantir que a pasta do usuario existe
295
296
  await this.http.post(
296
297
  `${this.serverUrl}/${this.basePath}/setup`,
297
- miniConf,
298
+ eitriConf,
298
299
  headers
299
300
  );
300
301
  console.log("Preparando ambiente de desenvolvimento");
301
302
  const response = await this.http.put(
302
303
  `${this.serverUrl}/${this.basePath}/version?command=push-version`,
303
- miniConf,
304
+ eitriConf,
304
305
  headers
305
306
  );
306
- miniConf.target = response.target;
307
+ eitriConf.target = response.application;
307
308
  const availableTargets = await this.availableTargets();
308
309
  let libs = TargetService.getLibsFromMiniConf(
309
- miniConf,
310
+ eitriConf,
310
311
  availableTargets
311
312
  );
312
313
  console.log("Ambiente pronto para compilação");
314
+ const eitriConfProperties = Object.getOwnPropertyNames(eitriConf)
315
+ const clientName = eitriConfProperties.find(p => p === libs.bifrost) || TargetService.LIBS_FOR_TARGET.MOBILE_NEW.bifrost
316
+ const componentsName = eitriConfProperties.find(p => p === libs.luminus) || TargetService.LIBS_FOR_TARGET.MOBILE_NEW.luminus
317
+
318
+ const bifrostVersion = eitriConf[clientName]
319
+ const luminusVersion = eitriConf[componentsName]
320
+
321
+ console.log("\nVersão sendo criada a partir das seguintes bibliotecas e suas respectivas versões:")
322
+ console.log(chalk.bold.green(`${clientName} [${bifrostVersion}]`))
313
323
  console.log(
314
- `${libs.components} [${miniConf[libs.components]}]\n${libs.superApp
315
- } [${miniConf[libs.superApp]}]`
324
+ chalk.bold.green(`${componentsName} [${luminusVersion}]`)
316
325
  );
317
326
  return { target: response.target };
318
327
  } catch (error) {
@@ -2,8 +2,7 @@ const QRCodeFactory = require("../QRCodeFactory");
2
2
  const readline = require("readline");
3
3
  const chalk = require("chalk");
4
4
  const os = require("os");
5
- const util = require('util')
6
- const exec = util.promisify(require("child_process").exec)
5
+ const EmulatorService = require("../EmulatorService");
7
6
 
8
7
  function QRCodeStarter(
9
8
  args,
@@ -69,33 +68,15 @@ async function tryOpenEmulator(fullUrl, args) {
69
68
  const shareId = extractShareId(fullUrl);
70
69
  const { emulator, deepLinks } = args;
71
70
  if(!deepLinks || deepLinks?.length < 1) {
72
- console.log("Seu application não contém deep links configurados.")
71
+ const warningMessages = [
72
+ 'Observamos que o seu Aplicativo não possui "deep links" configurados no momento.',
73
+ 'Para obter assistência na configuração, por favor, entre em contato com o nosso suporte técnico Eitri.',
74
+ 'Estamos aqui para ajudar a configurá-los para você.'
75
+ ]
76
+ console.log(warningMessages.join("\n"))
73
77
  return
74
78
  };
75
- for (const deepLink of deepLinks) {
76
- if (emulator === "ios") {
77
- const cmd = `xcrun simctl openurl booted ${deepLink}/${shareId}`
78
- const opened = await openDeepLink(cmd)
79
- if(opened) return;
80
- } else {
81
- const cmd = `adb shell am start -a android.intent.action.VIEW -d ${deepLink}/${shareId}`
82
- const opened = await openDeepLink(cmd)
83
- if(opened) return;
84
- }
85
- }
86
- }
87
-
88
- async function openDeepLink(cmd) {
89
- try {
90
- const {stderr} = await exec(cmd)
91
- if(stderr) {
92
- return false
93
- }
94
- return true
95
- } catch (error) {
96
- console.log(`Houve um erro ao tentar abrir o Eitri-App via deep link`)
97
- return process.exit(1)
98
- }
79
+ await EmulatorService.openSimulator(emulator, shareId, deepLinks)
99
80
  }
100
81
 
101
82
  async function listenerKeyPressToOpenEmulator(url, deepLinks) {
@@ -120,15 +101,20 @@ async function listenerKeyPressToOpenEmulator(url, deepLinks) {
120
101
  readline.emitKeypressEvents(process.stdin);
121
102
 
122
103
  process.stdin.on("keypress", async (chunk, key) => {
123
- if (key && key.name == "a") {
124
- const emulator = "android";
125
- console.log(`Abrindo Eitri-App no ${chalk.blue.bold("Android")}`);
126
- await tryOpenEmulator(url, { emulator, deepLinks });
127
- }
128
- if (os.platform() === "darwin" && key && key.name == "i") {
129
- const emulator = "ios";
130
- console.log(`Abrindo Eitri-App no ${chalk.blue.bold("iOS")}`);
131
- await tryOpenEmulator(url, { emulator, deepLinks });
104
+ try {
105
+ if (key && key.name == "a") {
106
+ const emulator = "android";
107
+ console.log(`Abrindo Eitri-App no ${chalk.blue.bold("Android")}`);
108
+ await tryOpenEmulator(url, {emulator, deepLinks});
109
+ }
110
+ if (os.platform() === "darwin" && key && key.name == "i") {
111
+ const emulator = "ios";
112
+ console.log(`Abrindo Eitri-App no ${chalk.blue.bold("iOS")}`);
113
+ await tryOpenEmulator(url, {emulator, deepLinks});
114
+ }
115
+ } catch (error) {
116
+ console.log(error);
117
+ process.exit(1);
132
118
  }
133
119
  });
134
120
  }
@@ -30,6 +30,12 @@ class GenericUtils {
30
30
  }
31
31
  }
32
32
 
33
+ static getSerialNumberFromAdb(deviceString = ""){
34
+ const regex = /^(\S+)\s+device/;
35
+ const serialNumber = RegExp(regex).exec(deviceString)
36
+ return serialNumber[1]
37
+ }
38
+
33
39
  }
34
40
 
35
41
  module.exports = GenericUtils