eitri-cli 1.0.4 → 1.1.0-beta

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