1 | const
|
2 | fs = require('fs-extra'),
|
3 | path = require('path'),
|
4 | merge = require('webpack-merge'),
|
5 | semver = require('semver')
|
6 |
|
7 | const
|
8 | appPaths = require('../app-paths'),
|
9 | logger = require('../helpers/logger'),
|
10 | warn = logger('app:extension(install)', 'red'),
|
11 | getPackageJson = require('../helpers/get-package-json'),
|
12 | getCallerPath = require('../helpers/get-caller-path'),
|
13 | extensionJson = require('./extension-json')
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | module.exports = class InstallAPI {
|
19 | constructor ({ extId, prompts }) {
|
20 | this.extId = extId
|
21 | this.prompts = prompts
|
22 | this.resolve = appPaths.resolve
|
23 | this.appDir = appPaths.appDir
|
24 |
|
25 | this.__needsNodeModulesUpdate = false
|
26 | this.__hooks = {
|
27 | renderFolders: [],
|
28 | exitLog: []
|
29 | }
|
30 | }
|
31 |
|
32 | |
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | getPersistentConf () {
|
39 | return extensionJson.getInternal(this.extId)
|
40 | }
|
41 |
|
42 | |
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 | setPersistentConf (cfg) {
|
49 | extensionJson.setInternal(this.extId, cfg || {})
|
50 | }
|
51 |
|
52 | |
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | mergePersistentConf (cfg = {}) {
|
60 | const currentCfg = this.getPersistentConf()
|
61 | this.setPersistentConf(merge(currentCfg, cfg))
|
62 | }
|
63 |
|
64 | |
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | compatibleWith (packageName, semverCondition) {
|
79 | const json = getPackageJson(packageName)
|
80 |
|
81 | if (json === void 0) {
|
82 | warn(`⚠️ Extension(${this.extId}): Dependency not found - ${packageName}. Please install it.`)
|
83 | process.exit(1)
|
84 | }
|
85 |
|
86 | if (!semver.satisfies(json.version, semverCondition)) {
|
87 | warn(`⚠️ Extension(${this.extId}): is not compatible with ${packageName} v${json.version}. Required version: ${semverCondition}`)
|
88 | process.exit(1)
|
89 | }
|
90 | }
|
91 |
|
92 | |
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | hasPackage (packageName, semverCondition) {
|
104 | const json = getPackageJson(packageName)
|
105 |
|
106 | if (json === void 0) {
|
107 | return false
|
108 | }
|
109 |
|
110 | return semverCondition !== void 0
|
111 | ? semver.satisfies(json.version, semverCondition)
|
112 | : true
|
113 | }
|
114 |
|
115 | |
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 | hasExtension (extId) {
|
123 | return extensionJson.has(extId)
|
124 | }
|
125 |
|
126 | |
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 | getPackageVersion (packageName) {
|
133 | const json = getPackageJson(packageName)
|
134 | return json !== void 0
|
135 | ? json.version
|
136 | : void 0
|
137 | }
|
138 |
|
139 | |
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | extendPackageJson (extPkg) {
|
146 | if (!extPkg) {
|
147 | return
|
148 | }
|
149 |
|
150 | if (typeof extPkg === 'string') {
|
151 | const
|
152 | dir = getCallerPath(),
|
153 | source = path.resolve(dir, extPkg)
|
154 |
|
155 | if (!fs.existsSync(source)) {
|
156 | warn()
|
157 | warn(`⚠️ Extension(${this.extId}): extendPackageJson() - cannot locate ${extPkg}. Skipping...`)
|
158 | warn()
|
159 | return
|
160 | }
|
161 | if (fs.lstatSync(source).isDirectory()) {
|
162 | warn()
|
163 | warn(`⚠️ Extension(${this.extId}): extendPackageJson() - "${extPkg}" is a folder instead of file. Skipping...`)
|
164 | warn()
|
165 | return
|
166 | }
|
167 |
|
168 | try {
|
169 | extPkg = require(source)
|
170 | }
|
171 | catch (e) {
|
172 | warn(`⚠️ Extension(${this.extId}): extendPackageJson() - "${extPkg}" is malformed`)
|
173 | warn()
|
174 | process.exit(1)
|
175 | }
|
176 | }
|
177 |
|
178 | if (Object(extPkg) !== extPkg || Object.keys(extPkg).length === 0) {
|
179 | return
|
180 | }
|
181 |
|
182 | const
|
183 | filePath = appPaths.resolve.app('package.json'),
|
184 | pkg = merge(require(filePath), extPkg)
|
185 |
|
186 | fs.writeFileSync(
|
187 | filePath,
|
188 | JSON.stringify(pkg, null, 2),
|
189 | 'utf-8'
|
190 | )
|
191 |
|
192 | if (
|
193 | extPkg.dependencies ||
|
194 | extPkg.devDependencies ||
|
195 | extPkg.optionalDependencies ||
|
196 | extPkg.bundleDependencies ||
|
197 | extPkg.peerDependencies
|
198 | ) {
|
199 | this.__needsNodeModulesUpdate = true
|
200 | }
|
201 | }
|
202 |
|
203 | |
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 | extendJsonFile (file, newData) {
|
211 | if (newData !== void 0 && Object(newData) === newData && Object.keys(newData).length > 0) {
|
212 | const
|
213 | filePath = appPaths.resolve.app(file),
|
214 | data = merge(fs.existsSync(filePath) ? require(filePath) : {}, newData)
|
215 |
|
216 | fs.writeFileSync(
|
217 | appPaths.resolve.app(file),
|
218 | JSON.stringify(data, null, 2),
|
219 | 'utf-8'
|
220 | )
|
221 | }
|
222 | }
|
223 |
|
224 | |
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 | render (templatePath, scope) {
|
232 | const
|
233 | dir = getCallerPath(),
|
234 | source = path.resolve(dir, templatePath),
|
235 | rawCopy = !scope || Object.keys(scope).length === 0
|
236 |
|
237 | if (!fs.existsSync(source)) {
|
238 | warn()
|
239 | warn(`⚠️ Extension(${this.extId}): render() - cannot locate ${templatePath}. Skipping...`)
|
240 | warn()
|
241 | return
|
242 | }
|
243 | if (!fs.lstatSync(source).isDirectory()) {
|
244 | warn()
|
245 | warn(`⚠️ Extension(${this.extId}): render() - "${templatePath}" is a file instead of folder. Skipping...`)
|
246 | warn()
|
247 | return
|
248 | }
|
249 |
|
250 | this.__hooks.renderFolders.push({
|
251 | source,
|
252 | rawCopy,
|
253 | scope
|
254 | })
|
255 | }
|
256 |
|
257 | |
258 |
|
259 |
|
260 |
|
261 |
|
262 | onExitLog (msg) {
|
263 | this.__hooks.exitLog.push(msg)
|
264 | }
|
265 |
|
266 | |
267 |
|
268 |
|
269 |
|
270 | __getHooks () {
|
271 | return this.__hooks
|
272 | }
|
273 | }
|