eitri-cli 1.6.1 → 1.7.0-beta.2

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.2",
4
4
  "description": "Command Line Interface to make \"Eitri-App\" with code and fire.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/src/cmd/start.js CHANGED
@@ -106,7 +106,13 @@ module.exports = async function start(args) {
106
106
  const friendlyMessage2 = "Recomendamos que verifique eventuais erros no código. Para mais informações, consulte nossa documentação em: https://docs.eitri.tech/."
107
107
  const friendlyMessage3 = "Se o problema persistir, por favor, entre em contato com o suporte técnico do Eitri."
108
108
  const friendlyMessage4 = "Você pode continuar o desenvolvimento localmente, mesmo que a sincronização não esteja disponível no momento."
109
- displayFriendlyErrorAtEnd = `\x1b[1m\x1b[31m\n${friendlyMessage1}\n${friendlyMessage2} \x1b[0m` + "\n" + `\n${friendlyMessage3}\n${friendlyMessage4}\n \x1b[0m`
109
+ displayFriendlyErrorAtEnd = `\x1b[1m\x1b[31m\n${friendlyMessage1}\n${friendlyMessage2} \x1b[0m` + "\n" + `\n${friendlyMessage3}\n${friendlyMessage4}\n\x1b[0m`
110
+
111
+ const errorData = error.response.data
112
+ const commonStartErrors = ['CodeCompileError', 'TagNotFound']
113
+ if(commonStartErrors.includes(errorData.name)) {
114
+ displayFriendlyErrorAtEnd += `\n\x1b[1m\x1b[31mMotivo: ${errorData.friendlyMessage}\x1b[0m\n`;
115
+ }
110
116
  }
111
117
  console.log("Pronto!");
112
118
 
@@ -161,8 +167,10 @@ module.exports = async function start(args) {
161
167
  await trackingService.sendError(e)
162
168
 
163
169
  process.exit(1)
164
- }finally{
170
+ } finally{
165
171
  if(displayFriendlyErrorAtEnd){
172
+ const folderHash = workspace.getFolderHashPath()
173
+ await workspace.transpile([folderHash])
166
174
  console.log("\n\n" + separator + "\n" + displayFriendlyErrorAtEnd + "\n" + separator + "\n\n")
167
175
  }
168
176
  }
@@ -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() {
@@ -22,8 +22,7 @@ class Watcher {
22
22
  const filePath = name.replace(/\\/g, '/')
23
23
  if (evt === 'remove') {
24
24
  console.log('Apagando', name)
25
- this.workspace.delete(filePath)
26
- return
25
+ return this.workspace.delete(filePath)
27
26
  }
28
27
  fs.stat(filePath, (err, stat) => {
29
28
  if (err) {
@@ -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) {
@@ -1001,6 +1010,11 @@ class Workspace {
1001
1010
  return Buffer.from(content).toString("base64");
1002
1011
  }
1003
1012
 
1013
+ getFolderHashPath() {
1014
+ const folderHashPath = path.join(this.folder2watch, 'folder.hash');
1015
+ return folderHashPath
1016
+ }
1017
+
1004
1018
  }
1005
1019
 
1006
1020
  module.exports = {
@@ -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