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.
- package/README.md +54 -0
- package/bitbucket-pipelines.toBeChanged.yml +64 -0
- package/boilerplate/mini-app-cafe-madeira.zip +0 -0
- package/check-version.js +12 -0
- package/config/default-eitri.js +1 -0
- package/config/dev.js +91 -0
- package/config/k8s-eitri.js +92 -0
- package/config/loc-eitri.js +92 -0
- package/config/prod-eitri.js +92 -0
- package/config/test-eitri.js +2 -0
- package/index-eitri.js +6 -0
- package/index.js +182 -0
- package/install-dev.bat +1 -0
- package/install-dev.sh +1 -0
- package/jest.config.js +6 -0
- package/jsconfig.json +9 -0
- package/package.json +80 -0
- package/publisher.js +53 -0
- package/src/cmd/clean.js +179 -0
- package/src/cmd/create.js +281 -0
- package/src/cmd/credentials.js +105 -0
- package/src/cmd/invite.js +87 -0
- package/src/cmd/list.js +36 -0
- package/src/cmd/login.js +51 -0
- package/src/cmd/manage-env.js +129 -0
- package/src/cmd/open-share.js +6 -0
- package/src/cmd/order-details.js +6 -0
- package/src/cmd/push-version.js +182 -0
- package/src/cmd/show-message-if-outdated-package.js +32 -0
- package/src/cmd/signup.js +69 -0
- package/src/cmd/start.js +171 -0
- package/src/cmd/tail-logs.js +26 -0
- package/src/cmd/test-initialization-params.js +6 -0
- package/src/cmd/validate.js +170 -0
- package/src/cmd/version.js +29 -0
- package/src/enum/WatcherOpts.js +3 -0
- package/src/enum/target.js +6 -0
- package/src/helpers/request-listener-helper.js +55 -0
- package/src/model/Payload.js +45 -0
- package/src/model/Target.js +76 -0
- package/src/model/User.js +11 -0
- package/src/service/AuthConfig.js +88 -0
- package/src/service/BlindGuardian.js +134 -0
- package/src/service/CliLogin.js +47 -0
- package/src/service/ConfigService.js +16 -0
- package/src/service/CredentialsService.js +47 -0
- package/src/service/GATrackingStrategy.js +16 -0
- package/src/service/HashFolder.js +79 -0
- package/src/service/Http.js +234 -0
- package/src/service/InviteService.js +45 -0
- package/src/service/ManageEnvService.js +10 -0
- package/src/service/MiniLog.js +132 -0
- package/src/service/QRCodeFactory.js +43 -0
- package/src/service/Server.js +239 -0
- package/src/service/StarterService.js +31 -0
- package/src/service/TagTree.js +101 -0
- package/src/service/TargetService.js +97 -0
- package/src/service/TrackService.js +11 -0
- package/src/service/TrackingEitriAnalytics.js +32 -0
- package/src/service/TrackingService.js +183 -0
- package/src/service/ValidateResult.js +57 -0
- package/src/service/Watcher.js +119 -0
- package/src/service/Workspace.js +1069 -0
- package/src/service/WorkspaceManager.js +74 -0
- package/src/service/factories/DoubtsStarterFactory.js +25 -0
- package/src/service/factories/MiniWebAppFactory.js +43 -0
- package/src/service/factories/QRCodeStarterFactory.js +78 -0
- package/src/service/factories/WebStarterFactory.js +88 -0
- package/src/service/factories/WoodCoffeeFactory.js +230 -0
- package/src/util/AboutTemplate.jsx +14 -0
- package/src/util/UrlUtils.js +12 -0
- package/src/util/UserLocalCredential.js +122 -0
- package/src/util/error-messages/error-messages.js +24 -0
- package/src/util/error-messages/invite/invite-error-messages.js +14 -0
- package/src/util/getCliVersion.js +13 -0
- package/src/util/getCreateFactory.js +9 -0
- package/src/util/ipv4.js +19 -0
- package/src/util/manage-env.js +65 -0
- package/src/util/open-docs.js +7 -0
- package/src/util/os.js +39 -0
- package/src/util/server-url.js +15 -0
- package/src/util/template-utils.js +21 -0
- package/src/view/index.html +19 -0
- package/targetMobileStickyness.md +47 -0
- package/targetWebStickyness.md +40 -0
- package/test/_fixtures/factory.js +30 -0
- package/test/_fixtures/miniWebApp/miniapp.conf.js +4 -0
- package/test/_fixtures/miniapp.conf.js +5 -0
- package/test/_fixtures/server/HelloWorldBackend.js +7 -0
- package/test/_fixtures/src/Home.js +5 -0
- package/test/_fixtures/src/Home2.js +5 -0
- package/test/_fixtures/src/commons/util.js +3 -0
- package/test/_fixtures/src/components/TagA.jsx +4 -0
- package/test/_fixtures/src/components/TagB.jsx +4 -0
- package/test/_fixtures/src/components/TagC.jsx +3 -0
- package/test/_fixtures/src/components/TagD.jsx +3 -0
- package/test/_fixtures/src/server/foo.js +7 -0
- package/test/_fixtures/src/views/AboutTemplate.jsx +14 -0
- package/test/_fixtures/woodcoffee/miniapp.conf.js +3 -0
- package/test/ame.conf.js +3 -0
- package/test/cmd/clean.test.js +66 -0
- package/test/cmd/create.test.js +252 -0
- package/test/cmd/credentials.test.js +159 -0
- package/test/cmd/list.test.js +74 -0
- package/test/cmd/manage-env.test.js +168 -0
- package/test/cmd/signup.test.js +20 -0
- package/test/cmd/start.test.js +5 -0
- package/test/miniapp.conf.js +3 -0
- package/test/model/Payload.test.js +35 -0
- package/test/service/BlindGuardian.test.js +84 -0
- package/test/service/CheckAmeConf.test.js +313 -0
- package/test/service/Http.test.js +312 -0
- package/test/service/InviteService.test.js +117 -0
- package/test/service/MiniWebAppFactory.test.js +40 -0
- package/test/service/TagTree.test.js +81 -0
- package/test/service/TargetService.test.js +48 -0
- package/test/service/TrackingService.test.js +105 -0
- package/test/service/UserAmeConf.test.js +47 -0
- package/test/service/WoodCoffeeFactory.test.js +148 -0
- package/test/service/Workspace.test.js +364 -0
- package/thinQrCode.md +58 -0
- package/v1.5.0.md +3 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
const axiosCookieJarSupport = require('axios-cookiejar-support').default
|
|
2
|
+
const FileCookieStore = require('tough-cookie-file-store').FileCookieStore
|
|
3
|
+
const CookieJar = require('tough-cookie').CookieJar
|
|
4
|
+
const { v4: uuidv4 } = require('uuid')
|
|
5
|
+
|
|
6
|
+
const os = require('os')
|
|
7
|
+
const path = require('path')
|
|
8
|
+
const getCliVersion = require('../util/getCliVersion')
|
|
9
|
+
|
|
10
|
+
const filePath = path.join(os.homedir(), './.eitri.cookie.json')
|
|
11
|
+
const jar = new CookieJar(new FileCookieStore(filePath))
|
|
12
|
+
|
|
13
|
+
const axios = require('axios').create({ withCredentials: true, jar })
|
|
14
|
+
|
|
15
|
+
axiosCookieJarSupport(axios)
|
|
16
|
+
|
|
17
|
+
let canShowLog = true
|
|
18
|
+
|
|
19
|
+
axios.interceptors.response.use(function (response) {
|
|
20
|
+
const YELLOW_COLOR = '\x1b[33m'
|
|
21
|
+
const BLUE_COLOR = '\x1b[94m'
|
|
22
|
+
const RESET_COLORS = '\x1b[0m'
|
|
23
|
+
const {warning} = response.data
|
|
24
|
+
const {greeting} = response.data
|
|
25
|
+
if(canShowLog) {
|
|
26
|
+
if(warning) {
|
|
27
|
+
console.warn(`${YELLOW_COLOR}\nAtenção: ${warning.message}${YELLOW_COLOR}${RESET_COLORS}\n`)
|
|
28
|
+
}
|
|
29
|
+
if(greeting) {
|
|
30
|
+
console.log(`${BLUE_COLOR}\n${greeting.message}${BLUE_COLOR}${RESET_COLORS}\n`)
|
|
31
|
+
}
|
|
32
|
+
canShowLog = (warning || greeting) ? false : true
|
|
33
|
+
}
|
|
34
|
+
return response
|
|
35
|
+
})
|
|
36
|
+
class Http {
|
|
37
|
+
constructor(tokenFactory) {
|
|
38
|
+
this.tokenFactory = tokenFactory
|
|
39
|
+
this.newTokenAttempt = 0
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
setTokenFactory(tokenFactory) {
|
|
43
|
+
this.tokenFactory = tokenFactory
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setToken(token) {
|
|
47
|
+
this.token = token
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getCookieSession(url) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
jar.getCookies(url, function (err, cookies) {
|
|
53
|
+
if (err) return reject(err)
|
|
54
|
+
resolve(cookies.find((cookie) => cookie))
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async post(url, data, headers) {
|
|
60
|
+
if (!this.token) {
|
|
61
|
+
this.token = await this.tokenFactory.getToken()
|
|
62
|
+
}
|
|
63
|
+
const mergedHeaders = {
|
|
64
|
+
...this._getHeader(), ...headers
|
|
65
|
+
}
|
|
66
|
+
return await axios.post(url, data, { headers: mergedHeaders })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async postForm(url, formData) {
|
|
70
|
+
if (!this.token) {
|
|
71
|
+
this.token = await this.tokenFactory.getToken()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const headers = {
|
|
75
|
+
...this._getHeader(),
|
|
76
|
+
'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`,
|
|
77
|
+
}
|
|
78
|
+
return await this._postForm(url, formData, headers)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_getHeader() {
|
|
82
|
+
const tid = uuidv4()
|
|
83
|
+
return {
|
|
84
|
+
Authorization: `Bearer ${this.token.accessToken}`,
|
|
85
|
+
'X-Transaction-Id': tid,
|
|
86
|
+
'App-Tools-Version': getCliVersion()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
__postForm(url, formData, headers, resolve, reject) {
|
|
91
|
+
axios.post(url, formData, { headers: headers })
|
|
92
|
+
.then((resp) => resolve(resp.data))
|
|
93
|
+
.catch((err) => this.rejectErrorPolitely({ err, methodName: '__postForm', url, formData, headers, resolve, reject }))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_postForm(url, formData, headers) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
this.__postForm(url, formData, headers, resolve, reject)
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async delete(url, options) {
|
|
103
|
+
if (!this.token) {
|
|
104
|
+
this.token = await this.tokenFactory.getToken()
|
|
105
|
+
}
|
|
106
|
+
const headers = this._getHeader()
|
|
107
|
+
return await this._delete(url, options, headers)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
__delete(url, data, headers, resolve, reject) {
|
|
111
|
+
axios.delete(url, { headers: headers, params: data.params })
|
|
112
|
+
.then((resp) => resolve(resp.data))
|
|
113
|
+
.catch((err) => this.rejectErrorPolitely({ err, methodName: '__delete', url, data, headers, resolve, reject }))
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
_delete(url, options, headers) {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
this.__delete(url, options, headers, resolve, reject)
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async get(url, options) {
|
|
123
|
+
options = options || {}
|
|
124
|
+
if (!this.token) {
|
|
125
|
+
this.token = await this.tokenFactory.getToken()
|
|
126
|
+
}
|
|
127
|
+
const headers = this._getHeader()
|
|
128
|
+
return await this._get({ url, options, headers })
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
_get(args) {
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
this.__get(args, resolve, reject)
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
__get(args, resolve, reject) {
|
|
138
|
+
const mergedHeaders = { ...args.headers, ...args.options.headers}
|
|
139
|
+
args.options.headers = mergedHeaders
|
|
140
|
+
axios
|
|
141
|
+
.get(args.url, args.options)
|
|
142
|
+
.then((result) => {
|
|
143
|
+
resolve(result.data)
|
|
144
|
+
})
|
|
145
|
+
.catch((err) => {
|
|
146
|
+
if (err.isAxiosError) {
|
|
147
|
+
this.newTokenAttempt++
|
|
148
|
+
if (err.response && err.response.status === 401 && this.newTokenAttempt < 3) {
|
|
149
|
+
this.tokenFactory
|
|
150
|
+
.getToken()
|
|
151
|
+
.then((token) => {
|
|
152
|
+
this.token = token
|
|
153
|
+
args.headers = this._getHeader()
|
|
154
|
+
this.__get(args, resolve, reject)
|
|
155
|
+
})
|
|
156
|
+
.catch(reject)
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
if (this.isError4xxWithMessage(err) || this.isError5xxWithMessage(err)) {
|
|
160
|
+
let error = new Error(`\n${err.response.data.error}`)
|
|
161
|
+
error.httpStatus = err.response.status
|
|
162
|
+
return reject(error)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
reject(err)
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async put(url, data, headers) {
|
|
170
|
+
data = data || {}
|
|
171
|
+
if (!this.token) {
|
|
172
|
+
this.token = await this.tokenFactory.getToken()
|
|
173
|
+
}
|
|
174
|
+
const mergedHeaders = { ...this._getHeader(), ...headers }
|
|
175
|
+
return await this._put(url, data, mergedHeaders)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
_put(url, data, headers) {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
this.__put(url, data, headers, resolve, reject)
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
__put(url, data, headers, resolve, reject) {
|
|
185
|
+
axios
|
|
186
|
+
.put(url, data, { headers })
|
|
187
|
+
.then((result) => resolve(result.data))
|
|
188
|
+
.catch((err) => this.rejectErrorPolitely({ err, methodName: '__put', url, data, headers, resolve, reject }))
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
rejectErrorPolitely(args) {
|
|
192
|
+
const { err, methodName, url, data, headers, resolve, reject } = args
|
|
193
|
+
|
|
194
|
+
if (process.env.LOG_LEVEL === 'full') console.error('Http.js:rejectErrorPolitely', err)
|
|
195
|
+
|
|
196
|
+
if (err.isAxiosError) {
|
|
197
|
+
this.newTokenAttempt++
|
|
198
|
+
if (err.response && err.response.status === 401 && this.newTokenAttempt < 3) {
|
|
199
|
+
this.tokenFactory
|
|
200
|
+
.getToken()
|
|
201
|
+
.then((token) => {
|
|
202
|
+
const newHeaders = this.updateToken(token.accessToken, headers)
|
|
203
|
+
this[methodName](url, data, newHeaders, resolve, reject)
|
|
204
|
+
})
|
|
205
|
+
.catch(reject)
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
if (this.isError4xxWithMessage(err) || this.isError5xxWithMessage(err)) {
|
|
209
|
+
let error = new Error(err.response.data.error)
|
|
210
|
+
error.httpStatus = err.response.status
|
|
211
|
+
error.response = { data: err.response.data }
|
|
212
|
+
|
|
213
|
+
return reject(error)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
reject(err)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
isError5xxWithMessage(err) {
|
|
220
|
+
return err.response && 500 <= err.response.status && err.response.status < 600 && err.response.data && typeof err.response.data.error === 'string'
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
isError4xxWithMessage(err) {
|
|
224
|
+
return err.response && 400 <= err.response.status && err.response.status < 500 && err.response.data && typeof err.response.data.error === 'string'
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
updateToken(token, headers) {
|
|
228
|
+
let headersCopy = { ...headers }
|
|
229
|
+
headersCopy['Authorization'] = `Bearer ${token}`
|
|
230
|
+
return headersCopy
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
module.exports = Http
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const config = require('config')
|
|
2
|
+
|
|
3
|
+
class InviteService {
|
|
4
|
+
|
|
5
|
+
constructor(workspace) {
|
|
6
|
+
this.workspace = workspace
|
|
7
|
+
this.conf = config.get('managerApi')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async findAllPending() {
|
|
11
|
+
let url = `${this.conf.url}${this.conf.invites.my}`
|
|
12
|
+
let invites = await this.workspace.http.get(url)
|
|
13
|
+
return invites.filter(inv => inv.status === 'ACTIVE')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async accept(inviteToAccept) {
|
|
17
|
+
if (!inviteToAccept) {
|
|
18
|
+
throw new Error('Convite indefinido')
|
|
19
|
+
}
|
|
20
|
+
let url = `${this.conf.url}${this.conf.invites.accept}`
|
|
21
|
+
await this.workspace.http.put(url, inviteToAccept)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async sendInvite(slug, email) {
|
|
25
|
+
let url = `${this.conf.url}${this.conf.invites.send}`
|
|
26
|
+
await this.workspace.http.post(url, { email, slug })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async findAllBySlug(slug) {
|
|
30
|
+
let url = `${this.conf.url}${this.conf.invites.slug}`.replace(':slug', slug)
|
|
31
|
+
let invites = await this.workspace.http.get(url)
|
|
32
|
+
return invites
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async remove(invite) {
|
|
36
|
+
if (!invite) {
|
|
37
|
+
throw new Error('Convite indefinido')
|
|
38
|
+
}
|
|
39
|
+
let url = `${this.conf.url}${this.conf.invites.remove}`.replace(':inviteToken', invite.token)
|
|
40
|
+
await this.workspace.http.delete(url, {})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = InviteService
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class ManageEnvService {
|
|
2
|
+
async getEnvVariables(workspace, url, miniConf, env, email, fileName) {
|
|
3
|
+
const { slug, version } = miniConf
|
|
4
|
+
const mountedQuery = `env=${env}&slug=${slug}&miniAppVersion=${version}&fileName=${fileName}&email=${email}`
|
|
5
|
+
const result = await workspace.http.get(`${url}/env?${mountedQuery}`)
|
|
6
|
+
return result
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = ManageEnvService
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const io = require('socket.io-client')
|
|
2
|
+
const chalk = require('chalk')
|
|
3
|
+
|
|
4
|
+
class MiniLog {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
if (!config) {
|
|
7
|
+
throw new Error('MiniLog config is required')
|
|
8
|
+
}
|
|
9
|
+
this._config = config
|
|
10
|
+
this.verbose = false
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
connect(roomName, silentOnConnect) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const socket = this.createSocket()
|
|
16
|
+
socket.on('connect', () => {
|
|
17
|
+
if(!silentOnConnect) console.log('Construindo para ', roomName)
|
|
18
|
+
socket.emit('joinRoom', roomName)
|
|
19
|
+
resolve()
|
|
20
|
+
})
|
|
21
|
+
socket.on('connect_error', (e) => {
|
|
22
|
+
if(silentOnConnect) console.error('NĂŁo foi possĂvel contectar ao compilador', roomName)
|
|
23
|
+
else console.error('NĂŁo foi possĂvel contectar ao compilador', roomName, `${this._config.url} ${this._config.path}`)
|
|
24
|
+
reject(e)
|
|
25
|
+
})
|
|
26
|
+
socket.on('onLog', (data) => {
|
|
27
|
+
this.printLog(data)
|
|
28
|
+
})
|
|
29
|
+
this.socket = socket
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
//TODO: ESSE MĂTODO DEVE SER APAGADO, QUANDO NĂO EXISTIR MAIS O COMANDO PUBLISH
|
|
33
|
+
awaitForPublish() {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
this.socket.on('onLog', (event) => {
|
|
36
|
+
if (!event.publish) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
if (event.publish.ok) {
|
|
40
|
+
resolve(event)
|
|
41
|
+
} else {
|
|
42
|
+
reject(new Error(event.publish.error))
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
awaitForBuild() {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
this.socket.on('onLog', (event) => {
|
|
51
|
+
if (!event.publish) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if (event.publish.ok) {
|
|
55
|
+
resolve(event)
|
|
56
|
+
} else {
|
|
57
|
+
reject(new Error(event.publish.error))
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
awaitForPushVersion() {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
this.socket.on('onLog', (event) => {
|
|
66
|
+
if (!event.publish) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
if (event.publish.ok) {
|
|
70
|
+
resolve(event)
|
|
71
|
+
} else {
|
|
72
|
+
reject(new Error(event.publish.error))
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createSocket() {
|
|
79
|
+
if (this._config.path) {
|
|
80
|
+
return io.connect(this._config.url, { path: this._config.path, transport: 'websocket' })
|
|
81
|
+
} else {
|
|
82
|
+
return io(this._config.url)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
format2JSON(str) {
|
|
87
|
+
let parsedToJSON
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
parsedToJSON = JSON.parse(str)
|
|
91
|
+
} catch (e) {
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return parsedToJSON
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
printLog(data) {
|
|
99
|
+
if (typeof data.msg === 'undefined') {
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
if (
|
|
103
|
+
typeof data.msg === 'string' &&
|
|
104
|
+
data.msg.includes(
|
|
105
|
+
'Download the React DevTools for a better development experience'
|
|
106
|
+
)
|
|
107
|
+
) {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (this.verbose) {
|
|
112
|
+
console.log(`\x1b[34meitri ${data.userAgent}\n\x1b[0m\x1b[90m${data.msg}\x1b[0m`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (/^START RequestId/.test(data.msg)) {
|
|
116
|
+
let msg = data.msg
|
|
117
|
+
.replace(/Version: \$LATEST/, '')
|
|
118
|
+
.split('\n')
|
|
119
|
+
.map((line) => line.replace(/^[0-9]+[^\t]+\t.*?\t/, ''))
|
|
120
|
+
.join('\n')
|
|
121
|
+
console.log(chalk.cyan(msg))
|
|
122
|
+
} else {
|
|
123
|
+
// A propriedade userFriendlyMessage deve ser tratada pelo miniapp. Logaremos da forma como o miniapp nos fornecer o objeto.
|
|
124
|
+
console.log(`\x1b[34meitri:\x1b[0m\x1b[97m${data.msg}\x1b[0m`);
|
|
125
|
+
}
|
|
126
|
+
if (data.stopCLI) {
|
|
127
|
+
process.exit(1)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = MiniLog
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const tmp = require('tmp')
|
|
2
|
+
const qrcode = require('qrcode')
|
|
3
|
+
|
|
4
|
+
// Fabrica de QR code :-)
|
|
5
|
+
class QRCodeFactory {
|
|
6
|
+
async create(data) {
|
|
7
|
+
console.log('==================================================')
|
|
8
|
+
console.log('Utilize o QR-Code para iniciar o seu eitri-app')
|
|
9
|
+
console.log('Ă importante utilizar o leitor de QR-Code do')
|
|
10
|
+
console.log('aplicativo Ă qual destina-se o seu eitri-app')
|
|
11
|
+
console.log('==================================================')
|
|
12
|
+
let qrCodeTempPath = await this.tempFile()
|
|
13
|
+
await this.createQRCodeImage(qrCodeTempPath, data)
|
|
14
|
+
return qrCodeTempPath
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
createQRCodeImage(qrCodeTempPath, data) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
qrcode.toFile(qrCodeTempPath, data, (err) => {
|
|
20
|
+
if (err) {
|
|
21
|
+
return reject(err)
|
|
22
|
+
}
|
|
23
|
+
resolve()
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
tempFile() {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
tmp.file(
|
|
31
|
+
{ prefix: 'eitri-qrcode-', postfix: '.png', keep: true },
|
|
32
|
+
function (err, tempPath) {
|
|
33
|
+
if (err) {
|
|
34
|
+
return reject(err)
|
|
35
|
+
}
|
|
36
|
+
resolve(tempPath)
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = QRCodeFactory
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const open = require('open')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const config = require('config')
|
|
5
|
+
const { URL } = require('url')
|
|
6
|
+
const Express = require('express')
|
|
7
|
+
const rateLimit = require('express-rate-limit')
|
|
8
|
+
const host = 'localhost'
|
|
9
|
+
const port = process.env.AME_APP_TOOLS_PORT || 3333
|
|
10
|
+
const TERMINAL_PRINTER_NAME = 'terminal'
|
|
11
|
+
let serverInstance
|
|
12
|
+
const requestListenerHelper = require('../helpers/request-listener-helper')
|
|
13
|
+
const CliLogin = require('./CliLogin')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const expressRateLimiter = rateLimit({
|
|
17
|
+
windowMs: 15 * 60 * 1000,
|
|
18
|
+
max: 100,
|
|
19
|
+
standardHeaders: true,
|
|
20
|
+
legacyHeaders: false,
|
|
21
|
+
})
|
|
22
|
+
class Server {
|
|
23
|
+
static stop(args) {
|
|
24
|
+
try {
|
|
25
|
+
if (serverInstance) {
|
|
26
|
+
serverInstance.close()
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
if (args.verbose) {
|
|
30
|
+
console.log(`Erro ao parar servidor local: ${e.message}`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static startServer(args) {
|
|
36
|
+
Server.stop(args)
|
|
37
|
+
const { qrCodePath, qrPrinter, verbose } = args
|
|
38
|
+
const requestListener = function (req, res) {
|
|
39
|
+
if (req.url === '/') {
|
|
40
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
|
41
|
+
res.writeHead(200)
|
|
42
|
+
|
|
43
|
+
let readStream = fs.createReadStream(
|
|
44
|
+
path.resolve(__dirname, '../view/index.html')
|
|
45
|
+
)
|
|
46
|
+
readStream.pipe(res)
|
|
47
|
+
} else {
|
|
48
|
+
res.setHeader('Content-Type', 'image/png')
|
|
49
|
+
res.writeHead(200)
|
|
50
|
+
|
|
51
|
+
let readStream = fs.createReadStream(qrCodePath)
|
|
52
|
+
readStream.pipe(res)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
serverInstance = Express().disable('x-powered-by')
|
|
57
|
+
serverInstance.use(expressRateLimiter)
|
|
58
|
+
serverInstance.use(requestListener)
|
|
59
|
+
|
|
60
|
+
serverInstance.listen(port, host, () => {
|
|
61
|
+
// Prioridade no printer informado pelo argumento do programa, depois o que foi informado na variavel de ambiente
|
|
62
|
+
if (!qrPrinter && !process.env.AAT_QRCODE_PRINTER) {
|
|
63
|
+
open(`http://${host}:${port}`)
|
|
64
|
+
} else if (qrPrinter && qrPrinter !== TERMINAL_PRINTER_NAME) {
|
|
65
|
+
open(`http://${host}:${port}`, { app: qrPrinter })
|
|
66
|
+
} else if (
|
|
67
|
+
process.env.AAT_QRCODE_PRINTER &&
|
|
68
|
+
process.env.AAT_QRCODE_PRINTER !== TERMINAL_PRINTER_NAME
|
|
69
|
+
) {
|
|
70
|
+
open(`http://${host}:${port}`, {
|
|
71
|
+
app: process.env.AAT_QRCODE_PRINTER,
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
if (verbose) {
|
|
75
|
+
console.log(`Server is running on http://${host}:${port}`)
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static startServerMinhaContaEmulator(args) {
|
|
81
|
+
Server.stop(args)
|
|
82
|
+
const { browser, verbose, bootstrapUrl, slug, http: workspaceHttp } = args
|
|
83
|
+
const ameSuperAppWebConfig = config.get('ameSuperAppWeb')
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* ParamĂȘtros do request listener definidos para o create server
|
|
87
|
+
* @param {Express.Request} req
|
|
88
|
+
* @param {Express.Response} res
|
|
89
|
+
* @returns
|
|
90
|
+
*/
|
|
91
|
+
const requestListener = function (req, res) {
|
|
92
|
+
if (req.url.startsWith('/workspace')) {
|
|
93
|
+
const url = `${config.workspace.url}${req.url}`
|
|
94
|
+
workspaceHttp
|
|
95
|
+
.get(url)
|
|
96
|
+
.then((workspaceRes) => {
|
|
97
|
+
res.header('Content-Type', 'text/html; charset=utf-8')
|
|
98
|
+
res.status(200).send(workspaceRes)
|
|
99
|
+
})
|
|
100
|
+
.catch((e) => {
|
|
101
|
+
console.log(e)
|
|
102
|
+
})
|
|
103
|
+
} else {
|
|
104
|
+
// res.header('Content-Type', 'text/html; charset=utf-8')
|
|
105
|
+
// res.writeHead(200)
|
|
106
|
+
|
|
107
|
+
let data = fs.readFileSync(
|
|
108
|
+
path.resolve(__dirname, '../view/ame_minha_conta_emulator.html'),
|
|
109
|
+
'utf8'
|
|
110
|
+
)
|
|
111
|
+
const _url = new URL(bootstrapUrl)
|
|
112
|
+
const finalUrl = bootstrapUrl.replace(
|
|
113
|
+
_url.origin,
|
|
114
|
+
`http://localhost:${port}`
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
data = data.replace('##ENVIRONMENT##', process.env.NODE_ENV === 'dev' ? 'dev' : 'hml' )
|
|
118
|
+
data = data.replace(
|
|
119
|
+
'##AME_SUPER_APP_SRC##',
|
|
120
|
+
ameSuperAppWebConfig.url
|
|
121
|
+
)
|
|
122
|
+
data = data.replace('##IFRAME_SRC##', finalUrl)
|
|
123
|
+
//TODO configurar o slug do mini-app corrente
|
|
124
|
+
data = data.replace('##SLUG##', slug)
|
|
125
|
+
return res.send(data)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
serverInstance = Express().disable('x-powered-by')
|
|
129
|
+
serverInstance.use(expressRateLimiter)
|
|
130
|
+
serverInstance.use(requestListener)
|
|
131
|
+
|
|
132
|
+
serverInstance.listen(port, host, () => {
|
|
133
|
+
open(`http://${host}:${port}`, { app: browser })
|
|
134
|
+
if (verbose) {
|
|
135
|
+
console.log(`Server is running on http://${host}:${port}`)
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static startServerEmulator(args) {
|
|
141
|
+
Server.stop(args)
|
|
142
|
+
const { browser, verbose, bootstrapUrl, slug, http: workspaceHttp } = args
|
|
143
|
+
const ameSuperAppWebConfig = config.get('ameSuperAppWeb')
|
|
144
|
+
console.log(bootstrapUrl)
|
|
145
|
+
|
|
146
|
+
const requestListener = function (req, res) {
|
|
147
|
+
if (req.url.startsWith('/workspace')) {
|
|
148
|
+
const url = `${config.workspace.url}${req.url}`
|
|
149
|
+
return requestListenerHelper(workspaceHttp, req.url, res, url)
|
|
150
|
+
} else {
|
|
151
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
|
152
|
+
res.writeHead(200)
|
|
153
|
+
|
|
154
|
+
let data = fs.readFileSync(
|
|
155
|
+
path.resolve(__dirname, '../view/emulator.html'),
|
|
156
|
+
'utf8'
|
|
157
|
+
)
|
|
158
|
+
const _url = new URL(bootstrapUrl)
|
|
159
|
+
const finalUrl = bootstrapUrl.replace(
|
|
160
|
+
_url.origin,
|
|
161
|
+
`http://localhost:${port}`
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
data = data.replace('##ENVIRONMENT##', process.env.NODE_ENV === 'dev' ? 'dev' : 'hml' )
|
|
165
|
+
data = data.replace('##IFRAME_SRC##', finalUrl)
|
|
166
|
+
data = data.replace(
|
|
167
|
+
'##AME_SUPER_APP_SRC##',
|
|
168
|
+
ameSuperAppWebConfig.url
|
|
169
|
+
)
|
|
170
|
+
//TODO configurar o slug do mini-app corrente
|
|
171
|
+
data = data.replace('##SLUG##', slug)
|
|
172
|
+
|
|
173
|
+
res.send(data)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
serverInstance = Express().disable('x-powered-by')
|
|
178
|
+
serverInstance.use(expressRateLimiter)
|
|
179
|
+
serverInstance.use(requestListener)
|
|
180
|
+
|
|
181
|
+
serverInstance.listen(port, host, () => {
|
|
182
|
+
open(`http://${host}:${port}`, { app: browser })
|
|
183
|
+
if (verbose) {
|
|
184
|
+
console.log(`Server is running on http://${host}:${port}`)
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static startMiniAppProxyServerAndOpenTarget(args) {
|
|
190
|
+
Server.stop(args)
|
|
191
|
+
const { verbose, openPath, http: workspaceHttp } = args
|
|
192
|
+
/**
|
|
193
|
+
* ParamĂȘtros do request listener definidos para o create server
|
|
194
|
+
* @param {Express.Request} req
|
|
195
|
+
* @param {Express.Response} res
|
|
196
|
+
* @returns
|
|
197
|
+
*/
|
|
198
|
+
const requestListener = function (req, res) {
|
|
199
|
+
let url = `${config.workspace.url}${req.url}`
|
|
200
|
+
return requestListenerHelper(workspaceHttp, req.url, res, url, verbose)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
serverInstance = Express().disable('x-powered-by')
|
|
204
|
+
serverInstance.use(expressRateLimiter)
|
|
205
|
+
serverInstance.use(requestListener)
|
|
206
|
+
serverInstance.listen(port, host, () => {
|
|
207
|
+
if (verbose) {
|
|
208
|
+
console.log(`Server is running on http://${host}:${port}`)
|
|
209
|
+
}
|
|
210
|
+
open(openPath)
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static startCliLogin(args) {
|
|
215
|
+
Server.stop(args)
|
|
216
|
+
const verbose = args?.verbose || ""
|
|
217
|
+
|
|
218
|
+
serverInstance = Express().disable('x-powered-by')
|
|
219
|
+
serverInstance.use(expressRateLimiter)
|
|
220
|
+
serverInstance.listen(port, host, () => {
|
|
221
|
+
if (verbose) {
|
|
222
|
+
console.log(`Server is running on http://${host}:${port}`)
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
serverInstance.get('/cli-login', async (req, res) => {
|
|
227
|
+
const {email, credential} = req?.query || {}
|
|
228
|
+
res.send('hello world')
|
|
229
|
+
await new CliLogin().saveCredentials({
|
|
230
|
+
email,
|
|
231
|
+
credential
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
return {host, port}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
module.exports = Server
|