UNPKG

5.99 kBJavaScriptView Raw
1const logger = require('../logger')
2const fsEx = require('fs-extra')
3const path = require('path')
4const findRoot = require('find-root')
5const { SETTINGS_FOLDER, EXTENSIONS_FOLDER, THEMES_FOLDER, TRUSTED_PIPELINES_FOLDER, PIPELINES_FOLDER } = require('../app/Constants')
6
7function filterDir (dirPath, filterFunction) {
8 if (!fsEx.pathExistsSync(dirPath)) {
9 logger.debug(`directory ${dirPath} does not exist`)
10 return []
11 }
12 return fsEx.readdirSync(dirPath).map(name => path.join(dirPath, name)).filter(filterFunction)
13}
14
15/**
16 * Returns all the sub dirs of a directory
17 * @param {string} dirPath
18 */
19function getDirectories (dirPath) {
20 return filterDir(dirPath, dir => fsEx.lstatSync(dir).isDirectory())
21}
22
23/**
24 * Filters all files of a directory optional by fileEnding
25 * @param {string} dirPath
26 * @param {string} [fileEnding]
27 */
28function getFiles (dirPath, fileEnding) {
29 return filterDir(dirPath, file => {
30 if (!fsEx.lstatSync(file).isFile()) return false
31 if (fileEnding) return file.endsWith(fileEnding)
32 return true
33 })
34}
35
36/**
37 * Removes a file if it exists
38 * @param {*} path
39 */
40function removeIfExists (path) {
41 if (fsEx.pathExistsSync(path)) {
42 fsEx.removeSync(path)
43 } else {
44 logger.debug(`file: ${path} does not exist`)
45 }
46}
47
48/**
49 * Resets the current project
50 */
51function resetProject () {
52 const appPath = getApplicationFolder()
53
54 removeIfExists(path.join(appPath, SETTINGS_FOLDER, 'app.json'))
55 removeIfExists(path.join(appPath, SETTINGS_FOLDER, 'storage.json'))
56 removeIfExists(path.join(appPath, SETTINGS_FOLDER, 'attachedExtension.json'))
57
58 const extensionsDir = path.join(appPath, EXTENSIONS_FOLDER)
59 const extensionDirs = getDirectories(extensionsDir)
60 extensionDirs.forEach(extensionDir => removeIfExists(path.join(extensionDir, 'extension', 'config.json')))
61
62 const themesDir = path.join(appPath, THEMES_FOLDER)
63 const themeDirs = getDirectories(themesDir)
64 themeDirs.forEach(themeDir => removeIfExists(path.join(themeDir, 'config', 'app.json')))
65 themeDirs.forEach(themeDir => removeIfExists(path.join(themeDir, 'config', 'components.json')))
66
67 const pipelinesDir = path.join(appPath, PIPELINES_FOLDER)
68 const pipelineFiles = getFiles(pipelinesDir)
69 pipelineFiles.forEach(pipelineFile => removeIfExists(pipelineFile))
70
71 const trustedPipelinesDir = path.join(appPath, TRUSTED_PIPELINES_FOLDER)
72 const trustedPipelineFiles = getFiles(trustedPipelinesDir)
73 trustedPipelineFiles.forEach(trustedPipelineFile => removeIfExists(trustedPipelineFile))
74}
75
76/**
77 * @param {string} processName
78 * @param {int} pid
79 * @param {string} dir
80 */
81async function setProcessFile (processName, dir, pid) {
82 await fsEx.writeJson(path.join(dir, processName), {pid})
83}
84
85/**
86 * @param {string} processName
87 * @param {string} dir
88 */
89async function deleteProcessFile (processName, dir) {
90 await fsEx.remove(path.join(dir, processName))
91}
92
93/**
94 * Returns pid of previous process or null
95 * @param {string} processName
96 * @param {string} dir
97 */
98async function previousProcess (processName, dir) {
99 const file = path.join(dir, processName)
100
101 // There's no process file
102 if (!await fsEx.pathExists(file)) return null
103
104 let processFileContent
105 try {
106 processFileContent = await fsEx.readJson(file)
107 } catch (e) {
108 throw new Error('Cannot read process file')
109 }
110
111 if (!processFileContent.pid) throw new Error('Process file is invalid')
112
113 try {
114 const isRunning = process.kill(processFileContent.pid, 0)
115 // File exists, pid has no process: must have been crashed
116 if (!isRunning) await deleteProcessFile(processName, dir)
117 return isRunning ? processFileContent.pid : null
118 } catch (e) {
119 return e.code === 'EPERM' ? processFileContent.pid : null
120 }
121}
122
123function getApplicationFolder () {
124 if (process.env.APP_PATH) return process.env.APP_PATH
125
126 try {
127 return findRoot(process.cwd(), (dir) => fsEx.existsSync(path.join(dir, '.sgcloud', 'app.json')))
128 } catch (err) {
129 // NOTE: workaround, find root would print "package.json not found in path"
130 err.message = "Couldn't find application folder upwards"
131 logger.debug(err)
132 }
133
134 return process.cwd()
135}
136
137/**
138 * @param {AppSettings} appSettings
139 */
140function generateComponentsJson (appSettings) {
141 const attachedExtensions = appSettings.loadAttachedExtensions()
142 const appFolder = appSettings.getApplicationFolder()
143 const extensionsFolder = path.join(appFolder, EXTENSIONS_FOLDER)
144
145 const components = {}
146 for (let extensionId in attachedExtensions) {
147 const extensionPath = path.join(extensionsFolder, attachedExtensions[extensionId].path)
148
149 const config = fsEx.readJsonSync(path.join(extensionPath, 'extension-config.json'))
150
151 if (config.components && config.components.length > 0) {
152 config.components.forEach((component) => {
153 if (!component.type) return // skip when the type of the component is missing
154 if (!components[component.type]) components[component.type] = {}
155 components[component.type][`${extensionId}/${component.id}`] = {
156 path: `${attachedExtensions[extensionId].path}/${component.path}`
157 }
158
159 if (component.target) components[component.type][`${extensionId}/${component.id}`].target = component.target
160 })
161 }
162 }
163
164 const themes = getDirectories(path.join(appFolder, THEMES_FOLDER))
165
166 logger.info(`Generating components.json for ${themes}`)
167
168 // write components.json for each theme
169 themes.forEach((theme) => {
170 if (!fsEx.existsSync(path.join(theme, 'extension-config.json'))) return
171 const configDir = path.join(theme, 'config')
172 const file = path.join(configDir, 'components.json')
173 try {
174 fsEx.ensureDirSync(configDir)
175 fsEx.writeJSONSync(file, components, {spaces: 2})
176 } catch (e) {
177 logger.warn(`writing "${file}" failed (${e.message})`)
178 }
179 })
180}
181
182module.exports = {
183 resetProject,
184 setProcessFile,
185 previousProcess,
186 deleteProcessFile,
187 getDirectories,
188 getFiles,
189 getApplicationFolder,
190 generateComponentsJson
191}