1 | const UnauthorizedError = require('../errors/UnauthorizedError')
|
2 | const logger = require('../logger')
|
3 | const { SETTINGS_FOLDER, EXTENSIONS_FOLDER, PIPELINES_FOLDER, TRUSTED_PIPELINES_FOLDER, THEMES_FOLDER } = require('../app/Constants')
|
4 | const inquirer = require('inquirer')
|
5 | const path = require('path')
|
6 | const fsEx = require('fs-extra')
|
7 | const utils = require('../utils/utils')
|
8 |
|
9 | const FOLDERS = [SETTINGS_FOLDER, EXTENSIONS_FOLDER, PIPELINES_FOLDER, TRUSTED_PIPELINES_FOLDER, THEMES_FOLDER]
|
10 |
|
11 | class InitAction {
|
12 | |
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | static register (caporal, appSettings, userSettings, dcHttpClient) {
|
19 | caporal
|
20 | .command('init')
|
21 | .description('Init the sdk')
|
22 | .option('--appId <appId>', 'set the Sandbox App ID you want to initialize')
|
23 | .option('--force', 'won\t ask for permission for overwriting previously set application')
|
24 | .action(async (args, options) => {
|
25 | try {
|
26 |
|
27 | const appId = await new InitAction(appSettings, userSettings, dcHttpClient).run(options)
|
28 | if (!appId) return logger.info('Init was aborted by user')
|
29 | logger.info(`The Application "${appId}" was successfully initialized`)
|
30 | } catch (err) {
|
31 | logger.error(err.message)
|
32 | process.exit(1)
|
33 | }
|
34 | })
|
35 | }
|
36 |
|
37 | |
38 |
|
39 |
|
40 |
|
41 |
|
42 | constructor (appSettings, userSettings, dcHttpClient) {
|
43 | this.appSettings = appSettings
|
44 | this.userSettings = userSettings
|
45 | this.dcHttpClient = dcHttpClient
|
46 | }
|
47 |
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 | async run (options) {
|
54 | this.options = options
|
55 | let appSettingsExists = true
|
56 |
|
57 |
|
58 | await this.userSettings.validate()
|
59 |
|
60 | try {
|
61 | await this.appSettings.validate()
|
62 | } catch (err) {
|
63 | appSettingsExists = false
|
64 | logger.debug('App settings are not present')
|
65 | }
|
66 |
|
67 | if (appSettingsExists) {
|
68 | if (!this.options.force) {
|
69 | const ignoreRunningProcesses = await this.checkForRunningProcesses(inquirer.prompt)
|
70 | if (!ignoreRunningProcesses) return false
|
71 |
|
72 | const ignoreAlreadyInitialized = await this.permitDeletion(inquirer.prompt, await this.appSettings.getId())
|
73 | if (!ignoreAlreadyInitialized) return false
|
74 | }
|
75 |
|
76 | const appId = await this.getAppId(inquirer.prompt)
|
77 | return this.initApplication(appId, this.userSettings, true)
|
78 | }
|
79 |
|
80 | const appId = await this.getAppId(inquirer.prompt)
|
81 | if (!appId) throw new Error('Sandbox App ID (--appId) is invalid')
|
82 |
|
83 | await Promise.all(FOLDERS.map(folder => {
|
84 | if (process.env.APP_PATH) folder = path.join(process.env.APP_PATH, folder)
|
85 | return fsEx.ensureDir(folder)
|
86 | }))
|
87 |
|
88 | return this.initApplication(appId, this.userSettings, false)
|
89 | }
|
90 |
|
91 | |
92 |
|
93 |
|
94 |
|
95 | async getAppId (prompt) {
|
96 | if (this.options.appId) return this.options.appId
|
97 |
|
98 | const answers = await prompt([{
|
99 | type: 'input',
|
100 | name: 'appId',
|
101 | message: 'Enter your Sandbox App ID:'
|
102 | }])
|
103 |
|
104 | return answers.appId
|
105 | }
|
106 |
|
107 | |
108 |
|
109 |
|
110 |
|
111 |
|
112 | async permitDeletion (prompt, appId) {
|
113 | const contentToBeDeleted = [
|
114 | ' - project related settings',
|
115 | ' - generated extension/theme config files',
|
116 | ' - active (trusted) pipelines'
|
117 | ].join('\n')
|
118 |
|
119 | logger.info(`The application ${appId} is currently initialized.\n\nReinit will delete the following project content:\n${contentToBeDeleted}`)
|
120 | const answers = await prompt({
|
121 | type: 'input',
|
122 | name: 'overwrite',
|
123 | default: 'n',
|
124 | message: `Do you really want to overwrite your current application (${appId})? (y/N)`
|
125 | })
|
126 |
|
127 | return answers.overwrite.charAt(0).toLowerCase() === 'y'
|
128 | }
|
129 |
|
130 | |
131 |
|
132 |
|
133 |
|
134 | async checkForRunningProcesses (prompt) {
|
135 | const processes = []
|
136 | if (await utils.getProcessId('backend', SETTINGS_FOLDER)) processes.push('backend')
|
137 | if (await utils.getProcessId('frontend', SETTINGS_FOLDER)) processes.push('frontend')
|
138 |
|
139 | if (processes.length > 0) {
|
140 | const answers = await prompt({
|
141 | type: 'input',
|
142 | name: 'ignore',
|
143 | default: 'n',
|
144 | message: `Processe(s): ${processes.join(', ')} running, reinit can cause problems in these processes; ignore? (y,N)`
|
145 | })
|
146 |
|
147 | return answers.ignore.charAt(0).toLowerCase() === 'y'
|
148 | }
|
149 |
|
150 | return true
|
151 | }
|
152 |
|
153 | |
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 | async initApplication (appId, userSettings, reset) {
|
160 | try {
|
161 | await this.dcHttpClient.getApplicationData(appId)
|
162 | if (reset) await utils.resetProject()
|
163 | await this.appSettings.setId(appId)
|
164 |
|
165 | return appId
|
166 | } catch (err) {
|
167 | logger.debug(err)
|
168 | if (err instanceof UnauthorizedError) throw new Error('You\'re not logged in! Please run `sgconnect login` again.')
|
169 | throw new Error(`The application ${appId} is not available or permissions are missing (message: ${err.message}). Please check the application at developer.shopgate.com!`)
|
170 | }
|
171 | }
|
172 | }
|
173 |
|
174 | module.exports = InitAction
|