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,1069 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const Http = require('./Http')
|
|
4
|
+
const Base64 = require('base-64')
|
|
5
|
+
const TagTree = require('./TagTree')
|
|
6
|
+
const FormData = require('form-data')
|
|
7
|
+
const { v4: uuidv4 } = require('uuid')
|
|
8
|
+
const config = require('config')
|
|
9
|
+
const AdmZip = require('adm-zip')
|
|
10
|
+
const BlindGuardian = require('./BlindGuardian')
|
|
11
|
+
const HashFolder = require('./HashFolder')
|
|
12
|
+
const packageJson = require(path.resolve(__dirname, '..', '..', 'package.json'))
|
|
13
|
+
const tempFolderPath = require('../util/os').OS_MAPPER
|
|
14
|
+
const TargetService = require('../service/TargetService')
|
|
15
|
+
const WatcherOpts = require('../enum/WatcherOpts')
|
|
16
|
+
const { default: axios } = require('../../node_modules/axios/index')
|
|
17
|
+
const ipv4 = require('../util/ipv4')
|
|
18
|
+
const { compressToBase64 } = require('lz-string')
|
|
19
|
+
const Buffer = require('buffer')
|
|
20
|
+
const DEFAULT_ENV = 'dev'
|
|
21
|
+
const cliProgress = require('cli-progress')
|
|
22
|
+
class Workspace {
|
|
23
|
+
constructor(blindGuardian, hashFolder) {
|
|
24
|
+
this.config = config.get('workspace')
|
|
25
|
+
this.basePath = this.config.basePath
|
|
26
|
+
this.blindGuardian = blindGuardian
|
|
27
|
+
this.hashFolder = hashFolder
|
|
28
|
+
this.folder2watch = ''
|
|
29
|
+
this.resourceFolders2watch = []
|
|
30
|
+
this.http = new Http(this.blindGuardian)
|
|
31
|
+
this.upsertQueue = []
|
|
32
|
+
this.requestNumber = 0
|
|
33
|
+
this.publishing = false
|
|
34
|
+
if (!this.config.colossus) {
|
|
35
|
+
console.warn('Missing colossus config inside workspace.')
|
|
36
|
+
}
|
|
37
|
+
this.shareApi = config.get('shareApi')
|
|
38
|
+
this.webhooks = []
|
|
39
|
+
this.targets = []
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @type {cliProgress.SingleBar}
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
this.progressBar
|
|
46
|
+
this.progressBarCounter = 0
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getTargets() {
|
|
50
|
+
return this.targets
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setTargets(targets) {
|
|
54
|
+
this.targets = targets
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getWebhooks () {
|
|
58
|
+
return this.webhooks
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setWebhooks(webhooks) {
|
|
62
|
+
this.webhooks = webhooks
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setServerUrl(url) {
|
|
66
|
+
this.serverUrl = url
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setQrCodeUrl(qrCodeUrl) {
|
|
70
|
+
this.qrCodeUrl = qrCodeUrl
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
setFolder2Watch(folderPath) {
|
|
74
|
+
this.folder2watch = folderPath
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setResourceFolder2Watch(resourceFolders2watch) {
|
|
78
|
+
this.resourceFolders2watch = resourceFolders2watch
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getResourceFolder2Watch() {
|
|
82
|
+
return this.resourceFolders2watch
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getTargetConfig(id, target) {
|
|
86
|
+
try{
|
|
87
|
+
const configs = await this.getAllTargetConfigs(target)
|
|
88
|
+
const config = configs.find(cfg => cfg.id === id)
|
|
89
|
+
|
|
90
|
+
if(!config) {
|
|
91
|
+
console.log(`TargetConfig [${target}] não encontrado, utilize o comando --list-target-configs para ver as configurações disponíveis`)
|
|
92
|
+
process.exit(1)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return [config]
|
|
96
|
+
} catch (e) {
|
|
97
|
+
console.log(`Erro ao buscar configuração: ${e}`)
|
|
98
|
+
process.exit(1)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async getAllTargetConfigs(target) {
|
|
103
|
+
const targetUrl = `${this.config.url}${this.config.targetPath}?name=${target}`
|
|
104
|
+
try{
|
|
105
|
+
const response = await axios.get(targetUrl)
|
|
106
|
+
const fullTarget = response.data
|
|
107
|
+
const configs = fullTarget[0].targetConfig
|
|
108
|
+
|
|
109
|
+
return configs
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.log(`Erro ao buscar configuração: ${e}`)
|
|
112
|
+
process.exit(1)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getTarget() {
|
|
117
|
+
|
|
118
|
+
if(!this.target) {
|
|
119
|
+
console.warn('Target não foi detectado no setup()')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return this.target
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async init() {
|
|
126
|
+
const token = await this.blindGuardian.getToken()
|
|
127
|
+
this.http.setToken(token)
|
|
128
|
+
this.userEmail = token.email
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getMiniConf() {
|
|
132
|
+
if (!this._miniConf) {
|
|
133
|
+
const miniAppConfPath = path.resolve(this.folder2watch, '../miniapp.conf.js')
|
|
134
|
+
if (!fs.existsSync(miniAppConfPath)) {
|
|
135
|
+
throw new Error('Por favor, verifique se você está dentro da pasta de um projeto eitri-app.')
|
|
136
|
+
}
|
|
137
|
+
this._miniConf = require(miniAppConfPath)
|
|
138
|
+
if (!this._miniConf.version) {
|
|
139
|
+
throw Error('Arquivo miniapp.conf.js sem version')
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return this._miniConf
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
setMiniConf(miniConf) {
|
|
146
|
+
this._miniConf = miniConf
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
const miniAppConfPath = path.resolve(this.folder2watch, '../miniapp.conf.js')
|
|
149
|
+
const jsonContent = JSON.stringify(miniConf, null, 4)
|
|
150
|
+
fs.writeFile(miniAppConfPath, `module.exports = ${jsonContent}`, (err) => {
|
|
151
|
+
if (err) {
|
|
152
|
+
console.log(err)
|
|
153
|
+
return reject(err)
|
|
154
|
+
}
|
|
155
|
+
resolve()
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async setup() {
|
|
161
|
+
const miniConf = this.getMiniConf()
|
|
162
|
+
const headers = {
|
|
163
|
+
'accept': this.config.libs.updateLibsEndpointVersion
|
|
164
|
+
}
|
|
165
|
+
const setupResponse = await this.http.post(`${this.serverUrl}/${this.basePath}/setup`, miniConf, headers) // somente para garantir que a pasta do usuario existe
|
|
166
|
+
|
|
167
|
+
console.log('Preparando compilador')
|
|
168
|
+
await this.http.put(`${this.serverUrl}/${this.basePath}/version`, miniConf, headers)// TODO PDV Setup fara isso aqui
|
|
169
|
+
console.log('Compilador pronto para uso contínuo')
|
|
170
|
+
|
|
171
|
+
const setupData = setupResponse.data
|
|
172
|
+
|
|
173
|
+
const { state, target: remoteTarget } = setupData
|
|
174
|
+
|
|
175
|
+
this.printLibsVersion(state)
|
|
176
|
+
|
|
177
|
+
await this.loadTarget(remoteTarget)
|
|
178
|
+
|
|
179
|
+
return setupData
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async loadTarget(remoteTarget) {
|
|
183
|
+
const targets = await this.availableTargets()
|
|
184
|
+
this.target = targets.find(t => t.name === remoteTarget.name)
|
|
185
|
+
|
|
186
|
+
if(!this.target) {
|
|
187
|
+
throw new Error('Workspace.loadTarget.internalError#missingTarget')
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
printLibsVersion(state) {
|
|
192
|
+
const miniConf = this.getMiniConf()
|
|
193
|
+
let libVersionsOutput = ''
|
|
194
|
+
state.libs.forEach(lib => {
|
|
195
|
+
let version = miniConf[lib.name]
|
|
196
|
+
if (version) {
|
|
197
|
+
// Captura a versao da lib quando estamos usando uma url
|
|
198
|
+
// "https://eitri.s3.amazonaws.com/eitri-app-client-0.8.0-alpha.tgz".match(/(\d+\.\d+\.\d+([-a-z]*))/)
|
|
199
|
+
const m = version.match(/(\d+\.\d+\.\d+([-a-z]*))/)
|
|
200
|
+
if (m) {
|
|
201
|
+
version = m[1]
|
|
202
|
+
}
|
|
203
|
+
libVersionsOutput += ` ${lib.name} [${version}]\n`
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
console.log(libVersionsOutput)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async checkVersions() {
|
|
210
|
+
try {
|
|
211
|
+
const miniConf = this.getMiniConf()
|
|
212
|
+
const headers = {
|
|
213
|
+
'accept': this.config.libs.updateLibsEndpointVersion
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// somente para garantir que a pasta do usuario existe
|
|
217
|
+
await this.http.post(`${this.serverUrl}/${this.basePath}/setup`, miniConf, headers)
|
|
218
|
+
console.log('Preparando ambiente de desenvolvimento')
|
|
219
|
+
const response = await this.http.put(`${this.serverUrl}/${this.basePath}/version?command=push-version`, miniConf, headers)
|
|
220
|
+
miniConf.target = response.target
|
|
221
|
+
const availableTargets = await this.availableTargets()
|
|
222
|
+
let libs = TargetService.getLibsFromMiniConf(miniConf, availableTargets)
|
|
223
|
+
console.log('Ambiente pronto para compilação')
|
|
224
|
+
console.log(`${libs.components} [${miniConf[libs.components]}]\n${libs.superApp} [${miniConf[libs.superApp]}]`)
|
|
225
|
+
return {target: response.target}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.log(`\x1b[1m\x1b[31m${error.message}\x1b[0m`);
|
|
228
|
+
process.exit(1)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
isDiff(miniConf, onlineVersion, packageName) {
|
|
233
|
+
return (
|
|
234
|
+
miniConf[packageName] &&
|
|
235
|
+
onlineVersion[packageName] !== miniConf[packageName]
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async getWorkspaceConnectionData(args, serverUrl) {
|
|
240
|
+
const cookie = await this.http.getCookieSession(serverUrl)
|
|
241
|
+
const miniConf = this.getMiniConf()
|
|
242
|
+
const viewHtml = (args.view || 'index')
|
|
243
|
+
let environment = process.env.NODE_ENV || DEFAULT_ENV
|
|
244
|
+
if (environment === 'prod') environment = 'prd'
|
|
245
|
+
let miniAppData = {
|
|
246
|
+
developerEmail: this.userEmail,
|
|
247
|
+
environment: environment,
|
|
248
|
+
albCookie: cookie.cookieString(),
|
|
249
|
+
orderId: args.orderId,
|
|
250
|
+
shareId: args.shareId,
|
|
251
|
+
slug: miniConf.slug,
|
|
252
|
+
publicKey: miniConf['public-key'] || miniConf.publicKey,
|
|
253
|
+
view: viewHtml
|
|
254
|
+
}
|
|
255
|
+
// delete miniAppData.albCookie
|
|
256
|
+
return Base64.encode(JSON.stringify(miniAppData))
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async getWorkspaceURL(args, targetConfig) {
|
|
260
|
+
args = args || {}
|
|
261
|
+
const cookie = await this.http.getCookieSession(this.serverUrl)
|
|
262
|
+
let paramOrderId = ''
|
|
263
|
+
let paramShareId = ''
|
|
264
|
+
let cid
|
|
265
|
+
const viewHtml = (args.view || 'index') + '.html'
|
|
266
|
+
const miniAppConf = this.getMiniConf()
|
|
267
|
+
const data = {
|
|
268
|
+
publicKey: miniAppConf['public-key'],
|
|
269
|
+
metadata: miniAppConf['metadata'],
|
|
270
|
+
slug: miniAppConf['slug'],
|
|
271
|
+
title: miniAppConf['title']
|
|
272
|
+
}
|
|
273
|
+
if (args.orderId) {
|
|
274
|
+
paramOrderId = '&orderId=' + encodeURIComponent(args.orderId)
|
|
275
|
+
}
|
|
276
|
+
if (args.shareId) {
|
|
277
|
+
paramShareId = '&shareId=' + encodeURIComponent(args.shareId)
|
|
278
|
+
}
|
|
279
|
+
if (args.initializationParams) {
|
|
280
|
+
data.initializationParams = args.initializationParams
|
|
281
|
+
}
|
|
282
|
+
const encodedData = Base64.encode(JSON.stringify(data))
|
|
283
|
+
if (cookie) {
|
|
284
|
+
cid = Base64.encode(cookie.cookieString())
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if(!targetConfig.bootstrapBaseUrl) {
|
|
288
|
+
throw new Error('Workspace.getWorkspaceURL.internalError#missingBootstrapBaseUrl')
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let miniAppUrl = `${this.getBootstrapURL(targetConfig.bootstrapBaseUrl)}/${this.config.basePath || 'workspace'}/user/${this.userEmail.replace(
|
|
292
|
+
'@',
|
|
293
|
+
'/',
|
|
294
|
+
)}/${viewHtml}?data=${encodedData}${paramOrderId}${paramShareId}&devmode=true`
|
|
295
|
+
|
|
296
|
+
if (cid) {
|
|
297
|
+
miniAppUrl = miniAppUrl + '&cid=' + cid
|
|
298
|
+
}
|
|
299
|
+
return miniAppUrl
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
*
|
|
304
|
+
* @param {string} bootstrapBaseUrl
|
|
305
|
+
*/
|
|
306
|
+
getBootstrapURL(bootstrapBaseUrl) {
|
|
307
|
+
const LOCALHOST = 'http://localhost:'
|
|
308
|
+
if (bootstrapBaseUrl.startsWith(LOCALHOST) && process.env.NODE_ENV === 'loc') {
|
|
309
|
+
const HOST = ipv4()[0]
|
|
310
|
+
const PORT = bootstrapBaseUrl.split(LOCALHOST)[1]
|
|
311
|
+
return `http://${HOST}:${PORT}`
|
|
312
|
+
}
|
|
313
|
+
return bootstrapBaseUrl
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async getNewWorkspaceURL(args, targetConfig) {
|
|
317
|
+
const qrCodeConfig = await this.getQrCodeConfig(args, targetConfig)
|
|
318
|
+
const stateData = await this.saveShareState(qrCodeConfig)
|
|
319
|
+
const stateId = stateData.id
|
|
320
|
+
const miniAppUrl = `${this.qrCodeUrl}/${stateId}?environment=${(process.env.NODE_ENV === 'hmlv2' ? 'hml' : process.env.NODE_ENV) || 'hml'}`
|
|
321
|
+
return {
|
|
322
|
+
miniAppConf: {
|
|
323
|
+
...qrCodeConfig,
|
|
324
|
+
shareId: stateId
|
|
325
|
+
},
|
|
326
|
+
miniAppUrl
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async saveShareState(qrCodeConfig) {
|
|
331
|
+
const createWorkspaceStateUrl = `${this.serverUrl}/${this.basePath}/share`
|
|
332
|
+
const requestBody = {
|
|
333
|
+
id: uuidv4(),
|
|
334
|
+
state: qrCodeConfig
|
|
335
|
+
}
|
|
336
|
+
const response = await this.http.post(createWorkspaceStateUrl, requestBody)
|
|
337
|
+
return response.data
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async getQrCodeConfig(args, targetConfig) {
|
|
341
|
+
args = args || {}
|
|
342
|
+
const cookie = await this.http.getCookieSession(this.serverUrl)
|
|
343
|
+
let cid
|
|
344
|
+
const miniAppConf = this.getMiniConf()
|
|
345
|
+
const view = (args.view || 'index') + '.html'
|
|
346
|
+
const initializationParams = args.initializationParams
|
|
347
|
+
const orderId = args.orderId
|
|
348
|
+
|
|
349
|
+
if (cookie) {
|
|
350
|
+
cid = Base64.encode(cookie.cookieString())
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const config = {
|
|
354
|
+
developerEmail: this.userEmail,
|
|
355
|
+
publicKey: miniAppConf['public-key'],
|
|
356
|
+
metadata: miniAppConf['metadata'],
|
|
357
|
+
slug: miniAppConf['slug'],
|
|
358
|
+
title: miniAppConf['title'],
|
|
359
|
+
permissions: miniAppConf['permissions'],
|
|
360
|
+
|
|
361
|
+
// Se nao enviarmos essa url pronta, o superapp tera que monta-la
|
|
362
|
+
// Essa url chama a funcao users.js do workspace-api
|
|
363
|
+
miniAppBootstrapUrl: await this.getWorkspaceURL(args, targetConfig),
|
|
364
|
+
initializationParams,
|
|
365
|
+
orderId,
|
|
366
|
+
view,
|
|
367
|
+
extras: {
|
|
368
|
+
cid // superapp joga tudo do extras na query string do bootstrapUrl .... Pq ja nao mandamos na queryString ja daqui?
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return config
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
getRelativePath(filePath) {
|
|
376
|
+
return filePath
|
|
377
|
+
.replace(this.folder2watch, '')
|
|
378
|
+
.replace(this.folder2watch.replace(/\\/g, '/'), '')
|
|
379
|
+
.replace(process.cwd(), '')
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async delete(filePath) {
|
|
383
|
+
const relPath = this.getRelativePath(filePath)
|
|
384
|
+
const url = `${this.serverUrl}/${this.basePath}/fileupload`
|
|
385
|
+
const params = {
|
|
386
|
+
filepath: relPath,
|
|
387
|
+
}
|
|
388
|
+
await this.http.delete(url, { params })
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
hasAccent(fileName) {
|
|
392
|
+
const fileRegex = /[À-ź]/g
|
|
393
|
+
const isValidFileName = !fileRegex.test(fileName)
|
|
394
|
+
return !isValidFileName
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
async upsert(filesPath, opts = {}, showProgressBar = false) {
|
|
399
|
+
if(showProgressBar) {
|
|
400
|
+
return await this.upsertConcurrency(filesPath, opts, showProgressBar)
|
|
401
|
+
}
|
|
402
|
+
return await this.upsertSequencial(filesPath, opts)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
async upsertSequencial(filePath, opts = {}) {
|
|
406
|
+
const fileName = path.basename(filePath)
|
|
407
|
+
|
|
408
|
+
const {isInvalid, promise} = await this.validateFileName(fileName, filePath)
|
|
409
|
+
if(isInvalid) return await promise
|
|
410
|
+
|
|
411
|
+
const holder = this.createPromiseHolder()
|
|
412
|
+
this.upsertQueue.push({
|
|
413
|
+
filePath,
|
|
414
|
+
opts,
|
|
415
|
+
holder,
|
|
416
|
+
requestNumber: this.requestNumber++,
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
const isSaving = opts.why === WatcherOpts.SAVE
|
|
420
|
+
|
|
421
|
+
if (!this.uploading) {
|
|
422
|
+
await this.execUpsertSequencial(isSaving)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return holder.promise
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
async upsertConcurrency(filesPath, opts = {}, showProgressBar = false) {
|
|
429
|
+
const promises = []
|
|
430
|
+
const isSaving = opts.why === WatcherOpts.SAVE
|
|
431
|
+
if(showProgressBar) {
|
|
432
|
+
this.createProgressBar(showProgressBar)
|
|
433
|
+
this.progressBar.start(filesPath.length, 0)
|
|
434
|
+
this.progressBar.update(this.progressBarCounter)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
for(const filePath of filesPath) {
|
|
438
|
+
const fileName = path.basename(filePath)
|
|
439
|
+
|
|
440
|
+
const {isInvalid, promise} = await this.validateFileName(fileName, filePath)
|
|
441
|
+
if(isInvalid) return await promise
|
|
442
|
+
|
|
443
|
+
const upsertFile = {
|
|
444
|
+
filePath,
|
|
445
|
+
opts,
|
|
446
|
+
requestNumber: this.requestNumber++,
|
|
447
|
+
}
|
|
448
|
+
promises.push(this.execUpsertConcurrency(upsertFile, isSaving, showProgressBar))
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const promisesChunks = this.spliceArray(promises, 5)
|
|
452
|
+
const data = []
|
|
453
|
+
for (const promiseArray of promisesChunks) {
|
|
454
|
+
const result = await Promise.all(promiseArray)
|
|
455
|
+
data.push(...result)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if(isSaving) return data[0]
|
|
459
|
+
|
|
460
|
+
if(showProgressBar) {
|
|
461
|
+
this.progressBar.update(filesPath.length)
|
|
462
|
+
this.progressBar.stop()
|
|
463
|
+
}
|
|
464
|
+
return data
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async postFile(filePath, isSaving, opts) {
|
|
468
|
+
const start = new Date().getTime()
|
|
469
|
+
const relativePath = this.getRelativePath(filePath)
|
|
470
|
+
const fileName = path.basename(filePath)
|
|
471
|
+
if (relativePath.startsWith(this.config.colossus.watchUserDir)) {
|
|
472
|
+
const allFiles = await this.listFilesInCorrectOrder()
|
|
473
|
+
const commomModulesPaths = allFiles.filter(f => f.includes('src/commons'))
|
|
474
|
+
await this.postLambda(filePath, relativePath, isSaving, commomModulesPaths)
|
|
475
|
+
} else {
|
|
476
|
+
await this.postFormData(filePath, relativePath, opts)
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
start,
|
|
480
|
+
relativePath,
|
|
481
|
+
fileName
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
async execUpsertConcurrency(upsertFile, isSaving, showProgressBar = false) {
|
|
486
|
+
const { filePath, opts, requestNumber } = upsertFile
|
|
487
|
+
|
|
488
|
+
const {fileName, relativePath, start} = await this.postFile(filePath, isSaving, opts)
|
|
489
|
+
|
|
490
|
+
if(showProgressBar) {
|
|
491
|
+
this.progressBarCounter++
|
|
492
|
+
this.progressBar.update(this.progressBarCounter)
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
filePath,
|
|
496
|
+
relativePath,
|
|
497
|
+
requestNumber,
|
|
498
|
+
time: new Date().getTime() - start,
|
|
499
|
+
baseName: fileName
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
async execUpsertSequencial(isSaving) {
|
|
505
|
+
this.uploading = true
|
|
506
|
+
for (let i = 0; i < this.upsertQueue.length; i++) {
|
|
507
|
+
const { filePath, opts, holder, requestNumber } = this.upsertQueue[i]
|
|
508
|
+
|
|
509
|
+
try {
|
|
510
|
+
const {relativePath, start} = await this.postFile(filePath, isSaving, opts)
|
|
511
|
+
|
|
512
|
+
holder.resolve({
|
|
513
|
+
filePath,
|
|
514
|
+
relativePath,
|
|
515
|
+
requestNumber,
|
|
516
|
+
time: new Date().getTime() - start,
|
|
517
|
+
})
|
|
518
|
+
} catch (e) {
|
|
519
|
+
holder.reject(e)
|
|
520
|
+
break // na duvida se deve abortar a fila toda
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
this.upsertQueue = []
|
|
524
|
+
this.uploading = false
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
async validateFileName(fileName, filePath) {
|
|
528
|
+
const hasAccent = this.hasAccent(fileName)
|
|
529
|
+
let promise
|
|
530
|
+
if (hasAccent) {
|
|
531
|
+
const message = ` - No nome do arquivo possui um ou mais caracteres não permitidos: ${fileName}`
|
|
532
|
+
console.log(message)
|
|
533
|
+
|
|
534
|
+
promise = Promise.resolve({
|
|
535
|
+
filePath,
|
|
536
|
+
relativePath: this.getRelativePath(filePath),
|
|
537
|
+
time: 0,
|
|
538
|
+
requestNumber: this.requestNumber++,
|
|
539
|
+
message
|
|
540
|
+
})
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
isInvalid: hasAccent,
|
|
544
|
+
promise
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
createPromiseHolder() {
|
|
549
|
+
const holder = {}
|
|
550
|
+
holder.promise = new Promise((resolve, reject) => {
|
|
551
|
+
holder.resolve = resolve
|
|
552
|
+
holder.reject = reject
|
|
553
|
+
})
|
|
554
|
+
return holder
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
async postFormData(filePath, relativePath, opts) {
|
|
558
|
+
let conf = this.getMiniConf()
|
|
559
|
+
const formData = new FormData()
|
|
560
|
+
formData.append('filepath', relativePath)
|
|
561
|
+
formData.append('why', opts.why || '')
|
|
562
|
+
formData.append('file', fs.createReadStream(filePath))
|
|
563
|
+
formData.append('miniAppVersion', conf.version)
|
|
564
|
+
if (opts.forceTranspile) {
|
|
565
|
+
formData.append('forceTranspile', opts.forceTranspile)
|
|
566
|
+
}
|
|
567
|
+
const url = `${this.serverUrl}/${this.basePath}/fileupload`
|
|
568
|
+
return await this.http.postForm(url, formData)
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
getEnvCode() {
|
|
572
|
+
if (!this.publishing) {
|
|
573
|
+
return 'ws'
|
|
574
|
+
}
|
|
575
|
+
if ([ 'dev', 'loc' ].includes(process.env.NODE_ENV)) {
|
|
576
|
+
return 'dev'
|
|
577
|
+
} else {
|
|
578
|
+
return 'hml'
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async postLambda(filePath, relativePath, isSaving, commomModulesPaths = []) {
|
|
583
|
+
|
|
584
|
+
let commomModules = commomModulesPaths.map(commomFilePath => {
|
|
585
|
+
let code = fs.readFileSync(commomFilePath, 'utf8')
|
|
586
|
+
|
|
587
|
+
let name = path.basename(commomFilePath)
|
|
588
|
+
|
|
589
|
+
let compressionResult = this.compressCode(code)
|
|
590
|
+
|
|
591
|
+
return { name, ...compressionResult }
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
let code = fs.readFileSync(filePath, 'utf8')
|
|
595
|
+
|
|
596
|
+
let compressionResult = this.compressCode(code)
|
|
597
|
+
|
|
598
|
+
let conf = this.getMiniConf()
|
|
599
|
+
const envCode = this.getEnvCode()
|
|
600
|
+
const fileName = path.basename(relativePath)
|
|
601
|
+
let data = {
|
|
602
|
+
slug: conf.slug,
|
|
603
|
+
envCode: envCode,
|
|
604
|
+
miniAppVersion: conf.version,
|
|
605
|
+
name: fileName,
|
|
606
|
+
code: compressionResult.code,
|
|
607
|
+
compressionType: compressionResult.compressionType,
|
|
608
|
+
publishing: this.publishing,
|
|
609
|
+
isSaving: isSaving,
|
|
610
|
+
restrictedLibs: conf['restricted-libs'],
|
|
611
|
+
webhooks: this.getCandidatedWebhook(fileName, conf),
|
|
612
|
+
commomModules
|
|
613
|
+
}
|
|
614
|
+
let url = `${this.config.colossus.url}`
|
|
615
|
+
const {data: responseData} = await this.http.post(url, data)
|
|
616
|
+
|
|
617
|
+
const {hookData} = responseData
|
|
618
|
+
if(hookData) {
|
|
619
|
+
const _webhooks = [...this.webhooks, hookData]
|
|
620
|
+
this.setWebhooks(_webhooks)
|
|
621
|
+
}
|
|
622
|
+
return responseData
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
getCandidatedWebhook(fileName, conf) {
|
|
626
|
+
const webhooks = conf['webhooks']
|
|
627
|
+
if(!webhooks || webhooks.length === 0) return undefined
|
|
628
|
+
const fileIsCandidatedToWebhook = webhooks.some(hook => hook.fileName === fileName)
|
|
629
|
+
const hook = [{fileName}]
|
|
630
|
+
return fileIsCandidatedToWebhook ? hook : undefined
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
async isSynchronized() {
|
|
634
|
+
const res = await Promise.all([
|
|
635
|
+
this.hashFolder.calculate(),
|
|
636
|
+
this.http.get(`${this.serverUrl}/${this.basePath}/fileupload`),
|
|
637
|
+
])
|
|
638
|
+
const folderHashValue = res[0]['hash']
|
|
639
|
+
const serverHash = res[1]['hash']
|
|
640
|
+
return folderHashValue === serverHash
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
async rmAllServerFiles() {
|
|
644
|
+
await this.delete('/')
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
async listFilesInCorrectOrder() {
|
|
648
|
+
const allFiles = await this.walk(this.folder2watch)
|
|
649
|
+
const componentsPath = path.join(this.folder2watch, 'components')
|
|
650
|
+
const componentTagRegExp = new RegExp(`${componentsPath}/[^/]+.jsx`)
|
|
651
|
+
const filesWithoutComponentTags = allFiles.filter(fileName => {
|
|
652
|
+
return !fileName.match(componentTagRegExp)
|
|
653
|
+
})
|
|
654
|
+
let files = filesWithoutComponentTags.sort((a, b) => {
|
|
655
|
+
if (a.includes('components') && !b.includes('components')) return -1
|
|
656
|
+
if (!a.includes('components') && b.includes('components')) return 1
|
|
657
|
+
if (a.includes('folder.hash')) return 1
|
|
658
|
+
if (b.includes('folder.hash')) return -1
|
|
659
|
+
return 0
|
|
660
|
+
})
|
|
661
|
+
const tagsFiles = await new TagTree().tagsFilesSorted(componentsPath)
|
|
662
|
+
files = tagsFiles.map(fileName => path.join(componentsPath, fileName)).concat(files)
|
|
663
|
+
return files
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
async getAllResourceFiles(resources) {
|
|
667
|
+
let allFiles = []
|
|
668
|
+
resources.forEach(async dir => {
|
|
669
|
+
const files = await this.walk(dir)
|
|
670
|
+
allFiles.push(...files)
|
|
671
|
+
})
|
|
672
|
+
return allFiles
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
async uploadAll() {
|
|
676
|
+
await this.mkdirs([this.folder2watch, ...this.resourceFolders2watch])
|
|
677
|
+
await this.rmAllServerFiles()
|
|
678
|
+
await this.hashFolder.updateHashFile()
|
|
679
|
+
|
|
680
|
+
const srcFiles = await this.listFilesInCorrectOrder()
|
|
681
|
+
const filesfromSrc = srcFiles.filter(f => !f.endsWith('folder.hash'))
|
|
682
|
+
const srcFolderHash = srcFiles.filter(f => f.endsWith('folder.hash'))
|
|
683
|
+
|
|
684
|
+
const resourceFiles = await this.getAllResourceFiles(this.resourceFolders2watch)
|
|
685
|
+
|
|
686
|
+
let files = resourceFiles.concat(filesfromSrc)
|
|
687
|
+
const componentFiles = files.filter(file => file.includes('/components'))
|
|
688
|
+
|
|
689
|
+
const opts = {
|
|
690
|
+
why: 'save',
|
|
691
|
+
log: false,
|
|
692
|
+
skipCompile: true,
|
|
693
|
+
}
|
|
694
|
+
const showProgressBar = true
|
|
695
|
+
if(componentFiles && componentFiles.length > 0) {
|
|
696
|
+
await this.preUpsert(componentFiles, opts)
|
|
697
|
+
}
|
|
698
|
+
await this.upsert(files, opts, showProgressBar)
|
|
699
|
+
await this.transpile(srcFolderHash)
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
async preUpsert(componentsFiles, opts) {
|
|
703
|
+
for (const filePath of componentsFiles) {
|
|
704
|
+
await this.upsertSequencial(filePath, opts)
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
async uploadZip() {
|
|
709
|
+
const admZip = new AdmZip()
|
|
710
|
+
await this.mkdirs([this.folder2watch, ...this.resourceFolders2watch])
|
|
711
|
+
await this.rmAllServerFiles()
|
|
712
|
+
await this.hashFolder.updateHashFile()
|
|
713
|
+
const allFiles = await this.listFilesInCorrectOrder()
|
|
714
|
+
const files = allFiles.filter(f => !f.endsWith('folder.hash'))
|
|
715
|
+
const folderHash = allFiles.filter(f => f.endsWith('folder.hash'))
|
|
716
|
+
const commomModulesPaths = allFiles.filter(f => f.includes('src/commons'))
|
|
717
|
+
|
|
718
|
+
for (let i = 0; i < files.length; i++) {
|
|
719
|
+
const filePath = files[i]
|
|
720
|
+
const filename = path.basename(filePath)
|
|
721
|
+
|
|
722
|
+
if (this.hasAccent(filename)) throw new Error(`Arquivo com um ou mais caracteres inválidos ${filename}`)
|
|
723
|
+
|
|
724
|
+
const relativePath = this.getRelativePath(filePath)
|
|
725
|
+
if (relativePath.startsWith(this.config.colossus.watchUserDir)) {
|
|
726
|
+
await this.postLambda(filePath, relativePath, false, commomModulesPaths)
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
admZip.addFile('__files_order.txt', allFiles.map(f => f.split(this.folder2watch)[1].replace(/\\/g, '/')).join('\n'))
|
|
731
|
+
admZip.addLocalFolder('./src')
|
|
732
|
+
|
|
733
|
+
console.log('Construindo')
|
|
734
|
+
|
|
735
|
+
const platform = process.platform
|
|
736
|
+
|
|
737
|
+
const zipPath = await this.resolveOs(platform)
|
|
738
|
+
admZip.writeZip(zipPath)
|
|
739
|
+
await this.sendZip(zipPath)
|
|
740
|
+
|
|
741
|
+
await this.transpile(folderHash)
|
|
742
|
+
|
|
743
|
+
console.log('Pronto')
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
async resolveOs(platform) {
|
|
747
|
+
let tempDir = ''
|
|
748
|
+
if (tempFolderPath[platform]) {
|
|
749
|
+
tempDir = await tempFolderPath[platform]()
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
tempDir = '.'
|
|
753
|
+
}
|
|
754
|
+
return tempDir + '/miniApp.zip'
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
async sendFiles(publishMessage) {
|
|
758
|
+
const miniConf = this.getMiniConf()
|
|
759
|
+
const formData = new FormData()
|
|
760
|
+
|
|
761
|
+
formData.append('miniAppName', miniConf.name || 'sem nome')
|
|
762
|
+
formData.append('miniAppSlug', miniConf.slug || 'sem-slug')
|
|
763
|
+
formData.append('miniAppTitle', miniConf.title || 'Sem Titulo')
|
|
764
|
+
formData.append('miniAppVersion', miniConf.miniAppVersion || miniConf.version || 'v1')
|
|
765
|
+
formData.append('organizationName', miniConf.organization.name)
|
|
766
|
+
formData.append('publishMessage', publishMessage || '')
|
|
767
|
+
|
|
768
|
+
const url = `${this.serverUrl}/${this.basePath}/publish?async=true`
|
|
769
|
+
await this.http.postForm(url, formData)
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
async sendZip(zip) {
|
|
773
|
+
const formData = new FormData()
|
|
774
|
+
formData.append('file', fs.createReadStream(zip))
|
|
775
|
+
const url = `${this.serverUrl}/${this.basePath}/uploadAll`
|
|
776
|
+
await this.http.postForm(url, formData)
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
async transpile(files) {
|
|
780
|
+
if (files.length > 0) {
|
|
781
|
+
return await this.upsert(...files, {
|
|
782
|
+
why: 'uploadAll',
|
|
783
|
+
log: false,
|
|
784
|
+
})
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
mkdirs(dirnames) {
|
|
789
|
+
return new Promise((resolve, reject) => {
|
|
790
|
+
dirnames.forEach(dirname => {
|
|
791
|
+
fs.mkdir(dirname, { recursive: true }, (err) => {
|
|
792
|
+
if (err) {
|
|
793
|
+
return reject(err)
|
|
794
|
+
}
|
|
795
|
+
resolve()
|
|
796
|
+
})
|
|
797
|
+
})
|
|
798
|
+
})
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async getFileNames(dir) {
|
|
802
|
+
const folder = path.resolve(this.folder2watch, dir)
|
|
803
|
+
const fileList = await this.walk(folder)
|
|
804
|
+
|
|
805
|
+
const fileNames = fileList.map(filePath => {
|
|
806
|
+
return path.basename(filePath)
|
|
807
|
+
})
|
|
808
|
+
|
|
809
|
+
return fileNames
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
async walk(dir) {
|
|
813
|
+
let results = []
|
|
814
|
+
const list = fs.readdirSync(dir)
|
|
815
|
+
for (let i = 0; i < list.length; i++) {
|
|
816
|
+
let file = list[i]
|
|
817
|
+
file = path.join(dir, file)
|
|
818
|
+
const stat = fs.statSync(file)
|
|
819
|
+
if (stat && stat.isDirectory()) {
|
|
820
|
+
/* Recurse into a subdirectory */
|
|
821
|
+
results = results.concat(await this.walk(file))
|
|
822
|
+
} else {
|
|
823
|
+
/* Is a file */
|
|
824
|
+
results.push(file)
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return results
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
//TODO: ESSE MÉTODO DEVE SER APAGADO, QUANDO NÃO EXISTIR MAIS O COMANDO PUBLISH
|
|
831
|
+
async publish(publishMessage) {
|
|
832
|
+
const miniConf = this.getMiniConf()
|
|
833
|
+
const formData = new FormData()
|
|
834
|
+
|
|
835
|
+
formData.append('miniAppName', miniConf.name || 'sem nome')
|
|
836
|
+
formData.append('miniAppSlug', miniConf.slug || 'sem-slug')
|
|
837
|
+
formData.append('miniAppTitle', miniConf.title || 'Sem Titulo')
|
|
838
|
+
formData.append('miniAppVersion', miniConf.miniAppVersion || miniConf.version || '0.1.0')
|
|
839
|
+
formData.append('organizationName', miniConf.organization.name)
|
|
840
|
+
formData.append('publishMessage', publishMessage || '')
|
|
841
|
+
|
|
842
|
+
const url = `${this.serverUrl}/${this.basePath}/publish?async=true`
|
|
843
|
+
await this.http.postForm(url, formData)
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
async build(buildMessage) {
|
|
847
|
+
const miniConf = this.getMiniConf()
|
|
848
|
+
const formData = new FormData()
|
|
849
|
+
|
|
850
|
+
formData.append('miniAppName', miniConf.name || 'sem nome')
|
|
851
|
+
formData.append('miniAppSlug', miniConf.slug || 'sem-slug')
|
|
852
|
+
formData.append('miniAppTitle', miniConf.title || 'Sem Titulo')
|
|
853
|
+
formData.append('miniAppVersion', miniConf.miniAppVersion || miniConf.version || 'v1')
|
|
854
|
+
formData.append('organizationName', miniConf.organization.name)
|
|
855
|
+
formData.append('publishMessage', buildMessage || '')
|
|
856
|
+
|
|
857
|
+
const url = `${this.serverUrl}/${this.basePath}/publish?async=true`
|
|
858
|
+
await this.http.postForm(url, formData)
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* @deprecated Prefira {@link Workspace#pushVersionAsJson}
|
|
863
|
+
*/
|
|
864
|
+
async pushVersionAsForm(buildMessage) {
|
|
865
|
+
const miniConf = this.getMiniConf()
|
|
866
|
+
const formData = new FormData()
|
|
867
|
+
|
|
868
|
+
let attrValue
|
|
869
|
+
|
|
870
|
+
formData.append('miniAppName', miniConf.name || 'sem nome')
|
|
871
|
+
formData.append('miniAppSlug', miniConf.slug || 'sem-slug')
|
|
872
|
+
formData.append('miniAppTitle', miniConf.title || 'Sem Titulo')
|
|
873
|
+
formData.append('miniAppVersion', miniConf.miniAppVersion || miniConf.version || 'v1')
|
|
874
|
+
formData.append('organizationName', miniConf.organization.name)
|
|
875
|
+
formData.append('miniAppSubSetName', miniConf.name)
|
|
876
|
+
formData.append('miniAppSubSetTitle', miniConf.title)
|
|
877
|
+
if ((attrValue = miniConf['eitri-app-components'])) formData.append('cliComponentsVersion', attrValue)
|
|
878
|
+
if ((attrValue = miniConf['eitri-app-client'])) formData.append('cliSuperAppClientVersion', attrValue)
|
|
879
|
+
if ((attrValue = packageJson.version)) formData.append('cliVersion', attrValue)
|
|
880
|
+
if ((attrValue = buildMessage)) formData.append('publishMessage', attrValue)
|
|
881
|
+
if ((attrValue = miniConf.privacy)) formData.append('privacy', JSON.stringify(attrValue))
|
|
882
|
+
|
|
883
|
+
const url = `${this.serverUrl}/${this.basePath}/publish?async=true`
|
|
884
|
+
await this.http.postForm(url, formData)
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
async pushVersionAsJson(buildMessage) {
|
|
888
|
+
let headers = {}
|
|
889
|
+
if(this.config.apiVersion && this.config.apiVersion.v2Header) {
|
|
890
|
+
headers = {
|
|
891
|
+
'accept': this.config.apiVersion.v2Header
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
const miniConf = this.getMiniConf()
|
|
895
|
+
const body = { miniConf, buildMessage, cliVersion: packageJson.version }
|
|
896
|
+
const url = `${this.serverUrl}/${this.basePath}/publish?async=true`
|
|
897
|
+
await this.http.post(url, body, headers)
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
async create(conf) {
|
|
901
|
+
const url = `${this.serverUrl}/${this.basePath}/create`
|
|
902
|
+
return await this.http.post(url, conf)
|
|
903
|
+
.then(res => res.data)
|
|
904
|
+
.catch(err => {
|
|
905
|
+
if (err.isAxiosError && err.response && err.response.status === 409 && err.response.data && err.response.data.error) {
|
|
906
|
+
console.log('Error: ' + err.response.data.error)
|
|
907
|
+
let dupError = new Error(err.response.data.error)
|
|
908
|
+
dupError.isDuplicatedError = true
|
|
909
|
+
dupError.field = err.response.data.field
|
|
910
|
+
throw dupError
|
|
911
|
+
}
|
|
912
|
+
console.log(err.message)
|
|
913
|
+
if (err && err.response) {
|
|
914
|
+
console.log(err.response.data)
|
|
915
|
+
}
|
|
916
|
+
throw err
|
|
917
|
+
})
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
async applyRolloutEnvironmentIfNeeded() {
|
|
921
|
+
const start = Date.now()
|
|
922
|
+
try {
|
|
923
|
+
const { slug } = this.getMiniConf()
|
|
924
|
+
const url = `${this.serverUrl}/${this.basePath}/users/miniapps/${slug}/actions/WORKSPACE_ROLLOUT`
|
|
925
|
+
const response = await this.http.get(url)
|
|
926
|
+
if (response.result) {
|
|
927
|
+
process.env['NODE_ENV'] = 'beta'
|
|
928
|
+
this.rollout = response.result
|
|
929
|
+
|
|
930
|
+
console.log('\n')
|
|
931
|
+
console.log('\t╔═══════════════════════════════════════╗')
|
|
932
|
+
console.log('\t║ Atenção: Utilizando Beta Workspace ║')
|
|
933
|
+
console.log('\t╚═══════════════════════════════════════╝\n')
|
|
934
|
+
}
|
|
935
|
+
} catch (e) {
|
|
936
|
+
if (process.env.LOG_LEVEL === 'full') {
|
|
937
|
+
console.log(e)
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
if (process.env.LOG_LEVEL === 'full') {
|
|
942
|
+
console.log('Check rollout time', Date.now() - start)
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
isRollout() {
|
|
947
|
+
return this.rollout
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// bff
|
|
951
|
+
async availableTargets() {
|
|
952
|
+
if(this.getTargets().length === 0) {
|
|
953
|
+
const url = `${this.serverUrl}/${this.basePath}/targets`
|
|
954
|
+
const options = {
|
|
955
|
+
headers: {
|
|
956
|
+
'Accept': 'application/vnd.workspace.api.v2+json'
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
const targets = await this.http.get(url, options)
|
|
960
|
+
this.setTargets(targets)
|
|
961
|
+
return targets
|
|
962
|
+
}
|
|
963
|
+
return this.getTargets()
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// local
|
|
967
|
+
getKnownAvailableTargets() {
|
|
968
|
+
return this.config.target.knownTargets
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
async getDefaultTarget() {
|
|
972
|
+
await this.availableTargets()
|
|
973
|
+
return this.getTargets().find(value => value.default)
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// client http configurado conforme as necessidades do workspace
|
|
977
|
+
getHttp() {
|
|
978
|
+
return this.http
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
async comparePermissions(target) {
|
|
982
|
+
const miniConf = this.getMiniConf()
|
|
983
|
+
const permissions = miniConf.permissions || []
|
|
984
|
+
const permissionsWithTarget = permissions.map(permission => ({...permission, target}))
|
|
985
|
+
const slug = miniConf.slug
|
|
986
|
+
const {data} = await this.http.post(`${this.serverUrl}/${this.basePath}/miniapps/${slug}/permissions/compare`, permissionsWithTarget)
|
|
987
|
+
const addedPermissions = []
|
|
988
|
+
const removedPermissions = []
|
|
989
|
+
if(data.diffCount > 0) {
|
|
990
|
+
data.result.forEach(result => {
|
|
991
|
+
if(result.status === 'added') {
|
|
992
|
+
addedPermissions.push(result.entity.permission)
|
|
993
|
+
} else {
|
|
994
|
+
removedPermissions.push(result.entity.permission)
|
|
995
|
+
}
|
|
996
|
+
})
|
|
997
|
+
}
|
|
998
|
+
return {addedPermissions, removedPermissions}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
async clean() {
|
|
1002
|
+
await this.getHttp().delete(`${this.serverUrl}/${this.basePath}/sources`, {})
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
compressCode(code) {
|
|
1006
|
+
const {SERVERLESS_CODE_COMPRESSION: compressionType, LOG_LEVEL} = process.env
|
|
1007
|
+
|
|
1008
|
+
let compressedCode, codeLength = code.length
|
|
1009
|
+
let maxPreviewLenth = 50
|
|
1010
|
+
let previewLength = codeLength > maxPreviewLenth ? maxPreviewLenth : codeLength
|
|
1011
|
+
|
|
1012
|
+
if(compressionType === 'base64') {
|
|
1013
|
+
compressedCode = this.toBase64(code)
|
|
1014
|
+
|
|
1015
|
+
if(LOG_LEVEL === 'full') {
|
|
1016
|
+
console.log(`Enviando arquivo sem compactacao em base64: ${code.substring(0, previewLength)}, codeLenth: ${codeLength}`)
|
|
1017
|
+
}
|
|
1018
|
+
} else if(compressionType === 'none'){
|
|
1019
|
+
if(LOG_LEVEL === 'full') {
|
|
1020
|
+
console.log(`Enviando arquivo sem qualquer compressao: ${code.substring(0, previewLength)}, codeLenth: ${codeLength}`)
|
|
1021
|
+
}
|
|
1022
|
+
} else if (!compressionType || compressionType === 'shrink') {
|
|
1023
|
+
compressedCode = compressToBase64(code)
|
|
1024
|
+
|
|
1025
|
+
if(LOG_LEVEL === 'full') {
|
|
1026
|
+
console.log(`File preview: ${code.substring(0, previewLength)}, Before compression: ${codeLength}, After compression: ${compressedCode.length}`)
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
return { code: compressedCode || code, compressionType: compressionType || 'shrink' }
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
toBase64(content) {
|
|
1035
|
+
return Buffer.from(content).toString('base64')
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
createProgressBar(showProgressBar) {
|
|
1039
|
+
if(showProgressBar) {
|
|
1040
|
+
this.progressBar = new cliProgress.SingleBar(
|
|
1041
|
+
{
|
|
1042
|
+
format:
|
|
1043
|
+
'Sincronizando [{bar}] {percentage}% | ETA: {eta}s | {value}/{total} Arquivos sincronizados...',
|
|
1044
|
+
},
|
|
1045
|
+
cliProgress.Presets.shades_classic,
|
|
1046
|
+
)
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
*
|
|
1052
|
+
* @param {unknown[]} array
|
|
1053
|
+
* @param {number} chunkCount
|
|
1054
|
+
* @returns {unknown[][]}
|
|
1055
|
+
*/
|
|
1056
|
+
spliceArray(array, chunkCount){
|
|
1057
|
+
var chunks = [], iterator, auxiliar
|
|
1058
|
+
for (iterator = 0, auxiliar = array.length; iterator < auxiliar; iterator += chunkCount) {
|
|
1059
|
+
chunks.push(array.slice(iterator, iterator + chunkCount))
|
|
1060
|
+
}
|
|
1061
|
+
return chunks
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
module.exports = {
|
|
1067
|
+
workspace: new Workspace(new BlindGuardian(), new HashFolder()),
|
|
1068
|
+
Workspace
|
|
1069
|
+
}
|