UNPKG

5.48 kBJavaScriptView Raw
1/**
2 * Various utility methods used in AEgir.
3 *
4 * @module aegir/utils
5 */
6'use strict'
7const { constants, createBrotliCompress, createGzip } = require('zlib')
8const os = require('os')
9const ora = require('ora')
10const extract = require('extract-zip')
11const stripComments = require('strip-json-comments')
12const stripBom = require('strip-bom')
13const { download } = require('@electron/get')
14const path = require('path')
15const findUp = require('findup-sync')
16const readPkgUp = require('read-pkg-up')
17const fs = require('fs-extra')
18const execa = require('execa')
19const pascalcase = require('pascalcase')
20const ghPages = require('gh-pages')
21const { promisify } = require('util')
22
23const publishPages = promisify(ghPages.publish)
24
25const { packageJson: pkg, path: pkgPath } = readPkgUp.sync({
26 cwd: fs.realpathSync(process.cwd())
27})
28const PKG_FILE = 'package.json'
29const DIST_FOLDER = 'dist'
30const SRC_FOLDER = 'src'
31
32exports.paths = {
33 dist: DIST_FOLDER,
34 src: SRC_FOLDER
35}
36exports.pkg = pkg
37// TODO: get this from aegir package.json
38exports.browserslist = '>1% or node >=10 and not ie 11 and not dead'
39exports.repoDirectory = path.dirname(pkgPath)
40exports.fromRoot = (...p) => path.join(exports.repoDirectory, ...p)
41exports.hasFile = (...p) => fs.existsSync(exports.fromRoot(...p))
42exports.fromAegir = (...p) => path.join(__dirname, '..', ...p)
43exports.hasTsconfig = exports.hasFile('tsconfig.json')
44
45exports.parseJson = (contents) => {
46 const data = stripComments(stripBom(contents))
47
48 // A tsconfig.json file is permitted to be completely empty.
49 if (/^\s*$/.test(data)) {
50 return {}
51 }
52
53 return JSON.parse(data)
54}
55
56exports.readJson = (filePath) => {
57 return exports.parseJson(fs.readFileSync(filePath, { encoding: 'utf-8' }))
58}
59
60exports.publishDocs = () => {
61 return publishPages(
62 'docs',
63 {
64 dotfiles: true,
65 message: 'chore: update documentation'
66 }
67 )
68}
69
70/**
71 * Get package version
72 *
73 * @returns {string} - version
74 */
75exports.pkgVersion = async () => {
76 const {
77 version
78 } = await fs.readJson(exports.getPathToPkg())
79 return version
80}
81
82/**
83 * Gets the top level path of the project aegir is executed in.
84 *
85 * @returns {string} - base path
86 */
87exports.getBasePath = () => {
88 return process.cwd()
89}
90
91exports.getPathToPkg = () => {
92 return path.join(exports.getBasePath(), PKG_FILE)
93}
94
95exports.getPathToDist = () => {
96 return path.join(exports.getBasePath(), DIST_FOLDER)
97}
98
99exports.getUserConfigPath = () => {
100 return findUp('.aegir.js')
101}
102
103exports.getUserConfig = () => {
104 let conf = {}
105 try {
106 const path = exports.getUserConfigPath()
107 if (!path) {
108 return {}
109 }
110 conf = require(path)
111 } catch (err) {
112 console.error(err) // eslint-disable-line no-console
113 }
114 return conf
115}
116
117/**
118 * Converts the given name from something like `peer-id` to `PeerId`.
119 *
120 * @param {string} name - lib name in kebab
121 * @returns {string} - lib name in pascal
122 */
123exports.getLibraryName = (name) => {
124 return pascalcase(name)
125}
126
127/**
128 * Get the absolute path to `node_modules` for aegir itself
129 */
130exports.getPathToNodeModules = () => {
131 return path.resolve(__dirname, '../node_modules')
132}
133
134/**
135 * Get the config for Listr.
136 *
137 * @returns {{renderer: 'verbose'}} - config for Listr
138 */
139exports.getListrConfig = () => {
140 return {
141 renderer: 'verbose'
142 }
143}
144
145exports.hook = (env, key) => (ctx) => {
146 if (ctx && ctx.hooks) {
147 if (ctx.hooks[env] && ctx.hooks[env][key]) {
148 return ctx.hooks[env][key]()
149 }
150 if (ctx.hooks[key]) {
151 return ctx.hooks[key]()
152 }
153 }
154
155 return Promise.resolve()
156}
157
158exports.exec = (command, args, options = {}) => {
159 const result = execa(command, args, options)
160
161 if (!options.quiet) {
162 result.stdout.pipe(process.stdout)
163 }
164
165 result.stderr.pipe(process.stderr)
166
167 return result
168}
169
170function getPlatformPath () {
171 const platform = process.env.npm_config_platform || os.platform()
172
173 switch (platform) {
174 case 'mas':
175 case 'darwin':
176 return 'Electron.app/Contents/MacOS/Electron'
177 case 'freebsd':
178 case 'openbsd':
179 case 'linux':
180 return 'electron'
181 case 'win32':
182 return 'electron.exe'
183 default:
184 throw new Error('Electron builds are not available on platform: ' + platform)
185 }
186}
187
188exports.getElectron = async () => {
189 const pkg = require('./../package.json')
190 const version = pkg.devDependencies.electron.slice(1)
191 const spinner = ora(`Downloading electron: ${version}`).start()
192 const zipPath = await download(version)
193 const electronPath = path.join(path.dirname(zipPath), getPlatformPath())
194 if (!fs.existsSync(electronPath)) {
195 spinner.text = 'Extracting electron to system cache'
196 await extract(zipPath, { dir: path.dirname(zipPath) })
197 }
198 spinner.succeed('Electron ready to use')
199 return electronPath
200}
201
202exports.brotliSize = (path) => {
203 return new Promise((resolve, reject) => {
204 let size = 0
205 const pipe = fs.createReadStream(path).pipe(createBrotliCompress({
206 params: {
207 [constants.BROTLI_PARAM_QUALITY]: 11
208 }
209 }))
210 pipe.on('error', reject)
211 pipe.on('data', buf => {
212 size += buf.length
213 })
214 pipe.on('end', () => {
215 resolve(size)
216 })
217 })
218}
219
220exports.gzipSize = (path) => {
221 return new Promise((resolve, reject) => {
222 let size = 0
223 const pipe = fs.createReadStream(path).pipe(createGzip({ level: 9 }))
224 pipe.on('error', reject)
225 pipe.on('data', buf => {
226 size += buf.length
227 })
228 pipe.on('end', () => {
229 resolve(size)
230 })
231 })
232}