eitri-cli 1.0.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.
Files changed (122) hide show
  1. package/README.md +54 -0
  2. package/bitbucket-pipelines.toBeChanged.yml +64 -0
  3. package/boilerplate/mini-app-cafe-madeira.zip +0 -0
  4. package/check-version.js +12 -0
  5. package/config/default-eitri.js +1 -0
  6. package/config/dev.js +91 -0
  7. package/config/k8s-eitri.js +92 -0
  8. package/config/loc-eitri.js +92 -0
  9. package/config/prod-eitri.js +92 -0
  10. package/config/test-eitri.js +2 -0
  11. package/index-eitri.js +6 -0
  12. package/index.js +182 -0
  13. package/install-dev.bat +1 -0
  14. package/install-dev.sh +1 -0
  15. package/jest.config.js +6 -0
  16. package/jsconfig.json +9 -0
  17. package/package.json +80 -0
  18. package/publisher.js +53 -0
  19. package/src/cmd/clean.js +179 -0
  20. package/src/cmd/create.js +281 -0
  21. package/src/cmd/credentials.js +105 -0
  22. package/src/cmd/invite.js +87 -0
  23. package/src/cmd/list.js +36 -0
  24. package/src/cmd/login.js +51 -0
  25. package/src/cmd/manage-env.js +129 -0
  26. package/src/cmd/open-share.js +6 -0
  27. package/src/cmd/order-details.js +6 -0
  28. package/src/cmd/push-version.js +182 -0
  29. package/src/cmd/show-message-if-outdated-package.js +32 -0
  30. package/src/cmd/signup.js +69 -0
  31. package/src/cmd/start.js +171 -0
  32. package/src/cmd/tail-logs.js +26 -0
  33. package/src/cmd/test-initialization-params.js +6 -0
  34. package/src/cmd/validate.js +170 -0
  35. package/src/cmd/version.js +29 -0
  36. package/src/enum/WatcherOpts.js +3 -0
  37. package/src/enum/target.js +6 -0
  38. package/src/helpers/request-listener-helper.js +55 -0
  39. package/src/model/Payload.js +45 -0
  40. package/src/model/Target.js +76 -0
  41. package/src/model/User.js +11 -0
  42. package/src/service/AuthConfig.js +88 -0
  43. package/src/service/BlindGuardian.js +134 -0
  44. package/src/service/CliLogin.js +47 -0
  45. package/src/service/ConfigService.js +16 -0
  46. package/src/service/CredentialsService.js +47 -0
  47. package/src/service/GATrackingStrategy.js +16 -0
  48. package/src/service/HashFolder.js +79 -0
  49. package/src/service/Http.js +234 -0
  50. package/src/service/InviteService.js +45 -0
  51. package/src/service/ManageEnvService.js +10 -0
  52. package/src/service/MiniLog.js +132 -0
  53. package/src/service/QRCodeFactory.js +43 -0
  54. package/src/service/Server.js +239 -0
  55. package/src/service/StarterService.js +31 -0
  56. package/src/service/TagTree.js +101 -0
  57. package/src/service/TargetService.js +97 -0
  58. package/src/service/TrackService.js +11 -0
  59. package/src/service/TrackingEitriAnalytics.js +32 -0
  60. package/src/service/TrackingService.js +183 -0
  61. package/src/service/ValidateResult.js +57 -0
  62. package/src/service/Watcher.js +119 -0
  63. package/src/service/Workspace.js +1069 -0
  64. package/src/service/WorkspaceManager.js +74 -0
  65. package/src/service/factories/DoubtsStarterFactory.js +25 -0
  66. package/src/service/factories/MiniWebAppFactory.js +43 -0
  67. package/src/service/factories/QRCodeStarterFactory.js +78 -0
  68. package/src/service/factories/WebStarterFactory.js +88 -0
  69. package/src/service/factories/WoodCoffeeFactory.js +230 -0
  70. package/src/util/AboutTemplate.jsx +14 -0
  71. package/src/util/UrlUtils.js +12 -0
  72. package/src/util/UserLocalCredential.js +122 -0
  73. package/src/util/error-messages/error-messages.js +24 -0
  74. package/src/util/error-messages/invite/invite-error-messages.js +14 -0
  75. package/src/util/getCliVersion.js +13 -0
  76. package/src/util/getCreateFactory.js +9 -0
  77. package/src/util/ipv4.js +19 -0
  78. package/src/util/manage-env.js +65 -0
  79. package/src/util/open-docs.js +7 -0
  80. package/src/util/os.js +39 -0
  81. package/src/util/server-url.js +15 -0
  82. package/src/util/template-utils.js +21 -0
  83. package/src/view/index.html +19 -0
  84. package/targetMobileStickyness.md +47 -0
  85. package/targetWebStickyness.md +40 -0
  86. package/test/_fixtures/factory.js +30 -0
  87. package/test/_fixtures/miniWebApp/miniapp.conf.js +4 -0
  88. package/test/_fixtures/miniapp.conf.js +5 -0
  89. package/test/_fixtures/server/HelloWorldBackend.js +7 -0
  90. package/test/_fixtures/src/Home.js +5 -0
  91. package/test/_fixtures/src/Home2.js +5 -0
  92. package/test/_fixtures/src/commons/util.js +3 -0
  93. package/test/_fixtures/src/components/TagA.jsx +4 -0
  94. package/test/_fixtures/src/components/TagB.jsx +4 -0
  95. package/test/_fixtures/src/components/TagC.jsx +3 -0
  96. package/test/_fixtures/src/components/TagD.jsx +3 -0
  97. package/test/_fixtures/src/server/foo.js +7 -0
  98. package/test/_fixtures/src/views/AboutTemplate.jsx +14 -0
  99. package/test/_fixtures/woodcoffee/miniapp.conf.js +3 -0
  100. package/test/ame.conf.js +3 -0
  101. package/test/cmd/clean.test.js +66 -0
  102. package/test/cmd/create.test.js +252 -0
  103. package/test/cmd/credentials.test.js +159 -0
  104. package/test/cmd/list.test.js +74 -0
  105. package/test/cmd/manage-env.test.js +168 -0
  106. package/test/cmd/signup.test.js +20 -0
  107. package/test/cmd/start.test.js +5 -0
  108. package/test/miniapp.conf.js +3 -0
  109. package/test/model/Payload.test.js +35 -0
  110. package/test/service/BlindGuardian.test.js +84 -0
  111. package/test/service/CheckAmeConf.test.js +313 -0
  112. package/test/service/Http.test.js +312 -0
  113. package/test/service/InviteService.test.js +117 -0
  114. package/test/service/MiniWebAppFactory.test.js +40 -0
  115. package/test/service/TagTree.test.js +81 -0
  116. package/test/service/TargetService.test.js +48 -0
  117. package/test/service/TrackingService.test.js +105 -0
  118. package/test/service/UserAmeConf.test.js +47 -0
  119. package/test/service/WoodCoffeeFactory.test.js +148 -0
  120. package/test/service/Workspace.test.js +364 -0
  121. package/thinQrCode.md +58 -0
  122. package/v1.5.0.md +3 -0
@@ -0,0 +1,31 @@
1
+ const QRCodeStarterFactory = require('./factories/QRCodeStarterFactory')
2
+ const DoubtsStarterFactory = require('./factories/DoubtsStarterFactory')
3
+ const WebStarterFactory = require('./factories/WebStarterFactory')
4
+
5
+
6
+ const strategy = require('./GATrackingStrategy')
7
+ async function handleStartServer(args, trackingService, watcher, workspace, factoryName, targetConfig, platform) {
8
+ const factories = {
9
+ mobile: new QRCodeStarterFactory(),
10
+ web: new WebStarterFactory(),
11
+ DOUBTS: new DoubtsStarterFactory()
12
+ }
13
+
14
+ const factory = platform ? factories[platform] : factories[factoryName]
15
+
16
+ if(!factory){
17
+ throw new Error('É necessário definir um valor válido, para o target, no miniapp.conf.js.')
18
+ }
19
+
20
+ let libsInfoForGA
21
+ if(strategy[factoryName]){
22
+ libsInfoForGA = strategy[factoryName](workspace.getMiniConf())
23
+ args['libsInfoForGA'] = libsInfoForGA
24
+ }
25
+
26
+
27
+ const starter = factory.create(args, trackingService, watcher, workspace, targetConfig)
28
+ await starter.startServer()
29
+ }
30
+
31
+ module.exports = handleStartServer
@@ -0,0 +1,101 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const cheerio = require('cheerio')
4
+
5
+ const TAG_EXT = '.jsx'
6
+ const extRegExp = new RegExp(`${TAG_EXT}$`)
7
+
8
+ class TagTree {
9
+ async tagsFilesSorted(tagsPath) {
10
+ let tagMap = await this.buildTagMap(tagsPath)
11
+ let stack = [],
12
+ visited = {}
13
+ for (let tagName in tagMap) {
14
+ if (!visited[tagName]) {
15
+ this.deepFirstSearch(tagMap[tagName], visited, stack)
16
+ }
17
+ }
18
+ return stack.map(tagObj => tagObj.fileName)
19
+ }
20
+
21
+ deepFirstSearch(tagObj, visited, stack) {
22
+ visited[tagObj.name] = true
23
+ tagObj.children.forEach(childTagObj => {
24
+ if (!visited[childTagObj.name]) {
25
+ this.deepFirstSearch(childTagObj, visited, stack)
26
+ }
27
+ })
28
+ stack.push(tagObj)
29
+ }
30
+
31
+ async buildTagMap(tagsPath) {
32
+ let tagMap = {}
33
+ let files = await this.listFiles(tagsPath, TAG_EXT)
34
+ for (let i = 0; i < files.length; i++) {
35
+ let fileName = files[i]
36
+ let htmlContent = await this.readTagContent(tagsPath, fileName)
37
+ let tags = this.extractTagsFromContent(htmlContent)
38
+ let tagName = fileName.replace(extRegExp, '')
39
+ tagMap[tagName] = {
40
+ name: tagName,
41
+ fileName: fileName,
42
+ childrenNames: tags.filter(tag => tag !== tagName),
43
+ children: []
44
+ }
45
+ }
46
+ for (let tagName in tagMap) {
47
+ let tagObj = tagMap[tagName]
48
+ tagObj.childrenNames.forEach(tag => {
49
+ let child = tagMap[tag]
50
+ if (child) {
51
+ tagObj.children.push(child)
52
+ }
53
+ })
54
+ delete tagObj['childrenNames']
55
+ }
56
+ return tagMap
57
+ }
58
+
59
+ readTagContent(tagsPath, fileName) {
60
+ return new Promise((resolve, reject) => {
61
+ fs.readFile(path.resolve(tagsPath, fileName), 'utf8', (err, data) => {
62
+ if (err) {
63
+ return reject(err)
64
+ }
65
+ resolve(data)
66
+ })
67
+ })
68
+ }
69
+
70
+ listFiles(tagsPath, extension) {
71
+ return new Promise((resolve, reject) => {
72
+ fs.exists(tagsPath, function(exists) {
73
+ if (!exists) {
74
+ return resolve([])
75
+ }
76
+ fs.readdir(tagsPath, function(err, files) {
77
+ if (err) {
78
+ return reject(err)
79
+ }
80
+ files = files.filter(
81
+ fileName => path.extname(fileName) === extension
82
+ )
83
+ resolve(files)
84
+ })
85
+ })
86
+ })
87
+ }
88
+
89
+ extractTagsFromContent(htmlContent) {
90
+ let $ = cheerio.load(htmlContent, { xml: { lowerCaseTags: false } })
91
+ let tags = {}
92
+ let ignore = { html: true, head: true, body: true, br: true }
93
+ $('*').each((i, el) => {
94
+ if (ignore[el.tagName.toLowerCase()]) return true
95
+ tags[el.tagName] = true
96
+ })
97
+ return Object.keys(tags).sort()
98
+ }
99
+ }
100
+
101
+ module.exports = TagTree
@@ -0,0 +1,97 @@
1
+ const config = require('config')
2
+ const targetEnum = require('../enum/target')
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
+ class TargetService{
18
+ constructor(workspace) {
19
+ this.workspace = workspace
20
+ this.conf = config.get('managerApi')
21
+ this.trustedMiniappTarget = null
22
+ }
23
+
24
+ async getTarget() {
25
+ if (this.trustedMiniappTarget) {
26
+ return this.trustedMiniappTarget
27
+ }
28
+ try{
29
+ const miniConf = this.workspace.getMiniConf()
30
+ let url = `${this.conf.url}${this.conf.miniapp.miniAppsPath}/${miniConf.slug}`
31
+ let miniapp = await this.workspace.http.get(url)
32
+ this.trustedMiniappTarget = miniapp.target
33
+ return this.trustedMiniappTarget
34
+
35
+ }catch(e){
36
+ throw new Error('Não identificamos um target válido: ' + e.message)
37
+ }
38
+ }
39
+
40
+ static getLibsFromMiniConf(miniConf, availableTargets) {
41
+ const target = availableTargets.find(t => t.name === miniConf.target)
42
+ if (target) {
43
+ return {
44
+ superApp: target.superAppClientLibName,
45
+ components: target.componentsLibName,
46
+ sdkSupport: target.sdkSupportLibName || LIBS_FOR_TARGET.MOBILE.sdkSupport
47
+ }
48
+ }
49
+ return LIBS_FOR_TARGET.MOBILE
50
+ }
51
+
52
+ async getLibs() {
53
+ let target = await this.getTarget()
54
+ const availableTargets = await this.workspace.availableTargets()
55
+ const targetExists = availableTargets.find(t => t.name === target)
56
+ if (!targetExists) {
57
+ throw new Error('Target inválido')
58
+ }
59
+ return targetExists
60
+ }
61
+
62
+ async getAppConfExampleSnippet() {
63
+ let target = await this.getTarget()
64
+ let libs = await this.getLibs()
65
+ const libsSnippet = '' +
66
+ ` // Versao dos componentes
67
+ "${libs.components}": "0.0.0",
68
+
69
+ // Versao do SDK
70
+ "${libs.superApp}": "0.0.0",` // close string
71
+
72
+
73
+ const targetSnippet = '' +
74
+ `
75
+
76
+ // Target
77
+ "target": "${target}"` // close string
78
+
79
+ let returnString = libsSnippet
80
+ if (target === targetEnum.AME_EMPRESAS_WEB || target === targetEnum.AME_MINHA_CONTA_WEB) {
81
+ returnString += targetSnippet
82
+ }
83
+ return returnString
84
+ }
85
+
86
+ /**
87
+ *
88
+ * @returns {Promise<Target[]>}
89
+ */
90
+ async getTargets() {
91
+ const targets = await this.workspace.availableTargets()
92
+ return targets
93
+ }
94
+
95
+ }
96
+
97
+ module.exports = TargetService
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ track: async function(miniConf, trackingService, libs) {
3
+ let event = {
4
+ ...libs,
5
+ miniAppSlug: miniConf.slug,
6
+ miniAppVersion: miniConf.version,
7
+ timeMs: 0,
8
+ }
9
+ await trackingService.sendStart(event)
10
+ }
11
+ }
@@ -0,0 +1,32 @@
1
+ const axios = require('axios')
2
+ const debug = require('debug')('ame-app-tools:TrackingService')
3
+ const config = require('config')
4
+ const EITRI_ANALYTICS_URL = config.get('eitriAnalytics')?.url
5
+
6
+ class TrackingEitriAnalytics {
7
+
8
+ static async sendEvent(input = {command: "", success: true, data: {}, errorMessage: ""}) {
9
+
10
+ try {
11
+ const event = {
12
+ command: `${input?.command}`,
13
+ success: `${input?.success}`,
14
+ data: {
15
+ ...(input?.data && typeof input?.data === "object" && !Object.keys(input?.data).length == 0) ? input?.data : undefined
16
+ }
17
+ }
18
+
19
+ if (input?.errorMessage && typeof input?.errorMessage === "string") {
20
+ event["errorMessage"] = input?.errorMessage?.replace("'", "")
21
+ }
22
+
23
+ await axios.post(EITRI_ANALYTICS_URL, event)
24
+ } catch (e) {
25
+ debug('Erro ao enviar evento ao Eitri Analytics', e?.message)
26
+ }
27
+
28
+ }
29
+
30
+ }
31
+
32
+ module.exports = TrackingEitriAnalytics
@@ -0,0 +1,183 @@
1
+ const path = require('path')
2
+ const axios = require('axios')
3
+ const os = require('os')
4
+ const TRACKING_ID = 'UA-98713437-6'
5
+ const packageJson = require(path.resolve(__dirname, '..', '..', 'package.json'))
6
+ const debug = require('debug')('eitri:TrackingService')
7
+ const GA_URL = 'https://www.google-analytics.com/collect'
8
+
9
+ class TrackingService {
10
+
11
+ constructor(blindGuardian, opts) {
12
+ let options = opts || {}
13
+ this.blindGuardian = blindGuardian
14
+ try {
15
+ this._clientId = this.blindGuardian.readClientCredentials().client_id
16
+ } catch(e) {
17
+ if (options.ignoreCredentialError) {
18
+ this._clientId = '58f9699a-ef9b-4b02-b406-c43f0e41738a'
19
+ } else {
20
+ throw e
21
+ }
22
+ }
23
+ }
24
+
25
+ getUserAgent() {
26
+ if (os.type() === 'Linux') {
27
+ return 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/83.0.4103.61 Chrome/83.0.4103.61 Safari/537.36'
28
+ }
29
+ if (os.type() === 'Windows_NT') {
30
+ return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246'
31
+ }
32
+ if (os.type() === 'Darwin') {
33
+ return 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9'
34
+ }
35
+ return 'axios/0.19.2'
36
+ }
37
+
38
+ async _send2GA(trackingId, documentLocation, timeMs) {
39
+ try {
40
+ const config = { headers: { 'User-Agent': this.getUserAgent() } }
41
+ config.params = {
42
+ v: '1',
43
+ t: 'pageview',
44
+ tid: trackingId,
45
+ dl: documentLocation,
46
+ cid: this._clientId,
47
+
48
+ // Page Load Time
49
+ plt: timeMs,
50
+
51
+ z: Math.round(Date.now() / 1000),
52
+ }
53
+ await axios.get(GA_URL, config)
54
+ } catch (e) {
55
+ debug('Erro ao enviar tracking de pageview', e.message)
56
+ }
57
+ }
58
+
59
+ async _sendError2GA(trackingId, documentLocation, error) {
60
+ try {
61
+ let errorMessage
62
+ const config = { headers: { 'User-Agent': this.getUserAgent() } }
63
+ if (typeof error === 'string') {
64
+ errorMessage = error
65
+ } else if (typeof error === 'object') {
66
+ errorMessage = error.message
67
+ } else {
68
+ errorMessage = `Tipo de erro nao suportado: ${typeof error}`
69
+ }
70
+ let source = 'no source'
71
+ if (typeof error === 'object' && error.stack) {
72
+ source = error.stack.split('\n')[1].trim().replace(/\/.+\//g, '')
73
+ source = `${errorMessage} ${source}`
74
+ }
75
+ config.params = {
76
+ v: 1,
77
+ t: 'exception', // exception nao aparece em real time :-(
78
+ exd: source,
79
+ exf: 0,
80
+ dl: documentLocation,
81
+ dt: errorMessage,
82
+ tid: trackingId,
83
+ cid: this._clientId,
84
+ z: Math.round(Date.now() / 1000),
85
+ }
86
+
87
+ await axios.get(GA_URL, config)
88
+ } catch (e) {
89
+ debug('Erro ao enviar tracking de erro', e.message)
90
+ }
91
+ }
92
+
93
+ async _sendEvent2GA(trackingId, documentLocation, event) {
94
+ try {
95
+ const config = { headers: { 'User-Agent': this.getUserAgent() } }
96
+ config.params = {
97
+ v: 1,
98
+ t: 'event', // exception nao aparece em real time :-(
99
+ ec: event.category,
100
+ ea: event.action,
101
+ el: event.label,
102
+ ev: event.value || 0,
103
+ dl: documentLocation,
104
+ dt: 'EventDt',
105
+ tid: trackingId,
106
+ cid: this._clientId,
107
+ z: Math.round(Date.now() / 1000),
108
+ }
109
+
110
+ await axios.get(GA_URL, config)
111
+ } catch (e) {
112
+ debug('Erro ao enviar tracking de evento', e.message)
113
+ }
114
+ }
115
+
116
+ async sendError(error) {
117
+ let documentLocation = [
118
+ `${process.env.NODE_ENV}`,
119
+ `v${packageJson.version}`
120
+ ].join('/') + '/'
121
+ await this._sendError2GA(TRACKING_ID, documentLocation, error)
122
+ }
123
+
124
+ async sendStart(event) {
125
+ await this.sendGeneric(event, 'start')
126
+ }
127
+
128
+ async sendSave(event) {
129
+ await this.sendGeneric(event, 'save')
130
+ }
131
+
132
+ async sendCompile(event) {
133
+ await this.sendGeneric(event, 'compile')
134
+ }
135
+
136
+ //TODO: ESSE MÉTODO DEVE SER APAGADO, QUANDO NÃO EXISTIR MAIS O COMANDO PUBLISH
137
+ async sendPublish(event) {
138
+ await this.sendGeneric(event, 'publish')
139
+ }
140
+
141
+ async sendBuild(event) {
142
+ await this.sendGeneric(event, 'build')
143
+ }
144
+
145
+ async sendPushedVersion(event) {
146
+ await this.sendGeneric(event, 'push-version')
147
+ }
148
+
149
+ async sendSignup() {
150
+ const eventName = 'signup'
151
+ let documentLocation = [
152
+ `${process.env.NODE_ENV}`,
153
+ `v${packageJson.version}`
154
+ ].join('/') + '/'
155
+ await this._send2GA(TRACKING_ID, documentLocation, 0)
156
+ await this._sendEvent2GA(TRACKING_ID, documentLocation, {
157
+ category: eventName,
158
+ action: eventName
159
+ })
160
+ }
161
+
162
+ async sendGeneric(event, eventName) {
163
+ let documentLocation = [
164
+ `${process.env.NODE_ENV || 'default'}`,
165
+ `v${packageJson.version}`,
166
+ event.componentsVersion ? `c${event.componentsVersion}` : `web_c${event.webComponentsVersion}`,
167
+ event.superClientVersion? `s${event.superClientVersion}` : `web_s${event.webSuperClientVersion}`,
168
+ // 'e', eventName,
169
+ 'ma', event.miniAppSlug,
170
+ `m${event.miniAppVersion}`
171
+ ].join('/') + '/'
172
+ await this._send2GA(TRACKING_ID, documentLocation, event.timeMs || 0)
173
+ await this._sendEvent2GA(TRACKING_ID, documentLocation, {
174
+ category: eventName,
175
+ action: eventName,
176
+ label: event.miniAppSlug,
177
+ value: event.timeMs
178
+ })
179
+ }
180
+
181
+ }
182
+
183
+ module.exports = TrackingService
@@ -0,0 +1,57 @@
1
+ class ValidateResult {
2
+ constructor(errors) {
3
+ this.errors = errors
4
+ }
5
+
6
+ addError(msg) {
7
+ this.errors.push(msg)
8
+ }
9
+
10
+ getErrors() {
11
+ return this.errors
12
+ }
13
+
14
+ isSuccess() {
15
+ return this.errors.length == 0
16
+ }
17
+
18
+ showExample() {
19
+ console.log(
20
+ 'Por favor, verifique atentamente os erros exibidos acima. Siga o exemplo abaixo: ' +
21
+ `
22
+ module.exports = {
23
+
24
+ // Dados da sua empresa
25
+ organization: {
26
+ "name": "Minha Empresa"
27
+ },
28
+
29
+ // Nome do seu mini app
30
+ "name": "Meu Mini App",
31
+
32
+ // Titulo do mini app, que vai em baixo do botao na pagina de transacoes
33
+ "title": "Meu super mini app",
34
+
35
+ // Chave para gerar a ordem/qrcode de pagamento (opcional)
36
+ "public-key": "",
37
+
38
+ // Identificador amigavel para colocar em uma url
39
+ "slug": "com.eitri.loja",
40
+
41
+ // Versao do mini app
42
+ "version": "1.0.0",
43
+
44
+ // Versao dos componentes
45
+ "eitri-app-components": "0.0.0",
46
+
47
+ // Versao do SDK
48
+ "eitri-app-client": "0.0.0",
49
+ };
50
+
51
+
52
+ `
53
+ )
54
+ }
55
+ }
56
+
57
+ module.exports = ValidateResult
@@ -0,0 +1,119 @@
1
+ const fs = require('fs')
2
+ const nodeWatch = require('node-watch')
3
+ const WatcherOpts = require('../enum/WatcherOpts')
4
+
5
+ class Watcher {
6
+ constructor(workspace, hashFolder, trackingService) {
7
+ this.workspace = workspace
8
+ this.hashFolder = hashFolder
9
+ this.trackingService = trackingService
10
+ }
11
+
12
+ getFolder2Watch() {
13
+ return this.workspace.folder2watch
14
+ }
15
+
16
+ start() {
17
+ console.log('\x1b[1m\x1b[32mEitri está observando a pasta abaixo:\x1b[0m');
18
+ console.log(this.getFolder2Watch(), ',', ...this.workspace.getResourceFolder2Watch())
19
+ this.mkdirs(this.getFolder2Watch())
20
+ const miniConf = this.workspace.getMiniConf()
21
+ nodeWatch(this.getFolder2Watch(), { recursive: true }, (evt, name) => {
22
+ const filePath = name.replace(/\\/g, '/')
23
+ if (evt === 'remove') {
24
+ console.log('Apagando', name)
25
+ this.workspace.delete(filePath)
26
+ return
27
+ }
28
+ fs.stat(filePath, (err, stat) => {
29
+ if (err) {
30
+ console.error(err)
31
+ return
32
+ }
33
+ if (stat.isFile()) {
34
+ console.log('\x1b[34mAlterações em: %s\x1b[0m', filePath)
35
+ this.workspace
36
+ .upsert(filePath, { why: WatcherOpts.SAVE })
37
+ .then((result) => {
38
+ let event = {
39
+ superClientVersion: miniConf['eitri-app-client'],
40
+ componentsVersion: miniConf['eitri-app-components'],
41
+ miniAppSlug: miniConf.slug,
42
+ miniAppVersion: miniConf.version,
43
+ timeMs: result.time,
44
+ }
45
+ if (result.relativePath === '/folder.hash') {
46
+
47
+ console.log(`\x1b[94mForjado em ${result.time} milissegundos\x1b[0m`);
48
+ this.trackingService.sendSave(event)
49
+ } else {
50
+ console.log(`\x1b[94mTransportado em ${result.time} milissegundos\x1b[0m`);
51
+ this.trackingService.sendCompile(event)
52
+ }
53
+ return this.hashFolder.updateHashFile()
54
+ })
55
+ .catch((err) => {
56
+ if (err.isAxiosError && err.response && err.response.status === 403) {
57
+ console.error('\nERRO: Credenciais expiradas')
58
+ } else if (err.response && err.response.data && err.response.data.friendlyMessage) {
59
+ console.error(`\nERRO: ${err.response.data.friendlyMessage}`)
60
+ } else if (err.message) {
61
+ console.error(`\nERRO: ${err.message}`)
62
+ } else {
63
+ console.error('\nErro inesperado [Watcher.start]')
64
+ }
65
+ })
66
+ }
67
+ })
68
+ })
69
+
70
+ const folders = this.workspace.getResourceFolder2Watch()
71
+ folders.forEach(folder =>
72
+ nodeWatch(folder, { recursive: true }, (evt, name) => {
73
+ this._handleWatch(evt, name)
74
+ })
75
+ )
76
+ }
77
+
78
+ mkdirs(dirname) {
79
+ return new Promise((resolve, reject) => {
80
+ fs.mkdir(dirname, { recursive: true }, (err) => {
81
+ if (err) {
82
+ return reject(err)
83
+ }
84
+ resolve()
85
+ })
86
+ })
87
+ }
88
+
89
+ _handleWatch(evt, name) {
90
+ const filePath = name.replace(/\\/g, '/')
91
+ if (evt === 'remove') {
92
+ console.log('Apagando', name)
93
+ this.workspace.delete(filePath)
94
+ return
95
+ }
96
+ fs.stat(filePath, (err, stat) => {
97
+ if (err) {
98
+ console.error(err)
99
+ return
100
+ }
101
+ if (stat.isFile()) {
102
+ console.log('Arquivo %s alterado.', filePath)
103
+ this.workspace
104
+ // o uso de forceTranspile permite que transpilemos independente de alterações no hash
105
+ .upsert(filePath, { why: 'save', forceTranspile: 'true' })
106
+ .then((result) => console.log(`Salvo ${result.time}ms`))
107
+ .catch((err) => {
108
+ if (err && err.message) {
109
+ console.log(err.message)
110
+ } else {
111
+ console.log('Erro inesperado [Watcher.start]')
112
+ }
113
+ })
114
+ }
115
+ })
116
+ }
117
+ }
118
+
119
+ module.exports = Watcher