UNPKG

5.05 kBJavaScriptView Raw
1"use strict";
2
3const fs = require('fs');
4
5const path = require('path');
6
7const rimraf = require('rimraf');
8
9const mkdirp = require('mkdirp');
10
11const arrify = require('arrify');
12
13const has = require('lodash.has');
14
15const readPkgUp = require('read-pkg-up');
16
17const which = require('which');
18
19const {
20 cosmiconfigSync
21} = require('cosmiconfig');
22
23const {
24 packageJson: pkg,
25 path: pkgPath
26} = readPkgUp.sync({
27 cwd: fs.realpathSync(process.cwd())
28});
29const appDirectory = path.dirname(pkgPath);
30
31function resolveKcdScripts() {
32 if (pkg.name === 'kcd-scripts') {
33 return require.resolve('./').replace(process.cwd(), '.');
34 }
35
36 return resolveBin('kcd-scripts');
37} // eslint-disable-next-line complexity
38
39
40function resolveBin(modName, {
41 executable = modName,
42 cwd = process.cwd()
43} = {}) {
44 let pathFromWhich;
45
46 try {
47 pathFromWhich = fs.realpathSync(which.sync(executable));
48 if (pathFromWhich && pathFromWhich.includes('.CMD')) return pathFromWhich;
49 } catch (_error) {// ignore _error
50 }
51
52 try {
53 const modPkgPath = require.resolve(`${modName}/package.json`);
54
55 const modPkgDir = path.dirname(modPkgPath);
56
57 const {
58 bin
59 } = require(modPkgPath);
60
61 const binPath = typeof bin === 'string' ? bin : bin[executable];
62 const fullPathToBin = path.join(modPkgDir, binPath);
63
64 if (fullPathToBin === pathFromWhich) {
65 return executable;
66 }
67
68 return fullPathToBin.replace(cwd, '.');
69 } catch (error) {
70 if (pathFromWhich) {
71 return executable;
72 }
73
74 throw error;
75 }
76}
77
78const fromRoot = (...p) => path.join(appDirectory, ...p);
79
80const hasFile = (...p) => fs.existsSync(fromRoot(...p));
81
82const ifFile = (files, t, f) => arrify(files).some(file => hasFile(file)) ? t : f;
83
84const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop));
85
86const hasPkgSubProp = pkgProp => props => hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`));
87
88const ifPkgSubProp = pkgProp => (props, t, f) => hasPkgSubProp(pkgProp)(props) ? t : f;
89
90const hasScript = hasPkgSubProp('scripts');
91const hasPeerDep = hasPkgSubProp('peerDependencies');
92const hasDep = hasPkgSubProp('dependencies');
93const hasDevDep = hasPkgSubProp('devDependencies');
94
95const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args));
96
97const ifPeerDep = ifPkgSubProp('peerDependencies');
98const ifDep = ifPkgSubProp('dependencies');
99const ifDevDep = ifPkgSubProp('devDependencies');
100
101const ifAnyDep = (deps, t, f) => hasAnyDep(arrify(deps)) ? t : f;
102
103const ifScript = ifPkgSubProp('scripts');
104
105function parseEnv(name, def) {
106 if (envIsSet(name)) {
107 try {
108 return JSON.parse(process.env[name]);
109 } catch (err) {
110 return process.env[name];
111 }
112 }
113
114 return def;
115}
116
117function envIsSet(name) {
118 return process.env.hasOwnProperty(name) && process.env[name] && process.env[name] !== 'undefined';
119}
120
121function getConcurrentlyArgs(scripts, {
122 killOthers = true
123} = {}) {
124 const colors = ['bgBlue', 'bgGreen', 'bgMagenta', 'bgCyan', 'bgWhite', 'bgRed', 'bgBlack', 'bgYellow'];
125 scripts = Object.entries(scripts).reduce((all, [name, script]) => {
126 if (script) {
127 all[name] = script;
128 }
129
130 return all;
131 }, {});
132 const prefixColors = Object.keys(scripts).reduce((pColors, _s, i) => pColors.concat([`${colors[i % colors.length]}.bold.reset`]), []).join(','); // prettier-ignore
133
134 return [killOthers ? '--kill-others-on-fail' : null, '--prefix', '[{name}]', '--names', Object.keys(scripts).join(','), '--prefix-colors', prefixColors, ...Object.values(scripts).map(s => JSON.stringify(s)) // stringify escapes quotes ✨
135 ].filter(Boolean);
136}
137
138function isOptedOut(key, t = true, f = false) {
139 if (!fs.existsSync(fromRoot('.opt-out'))) {
140 return f;
141 }
142
143 const contents = fs.readFileSync(fromRoot('.opt-out'), 'utf-8');
144 return contents.includes(key) ? t : f;
145}
146
147function isOptedIn(key, t = true, f = false) {
148 if (!fs.existsSync(fromRoot('.opt-in'))) {
149 return f;
150 }
151
152 const contents = fs.readFileSync(fromRoot('.opt-in'), 'utf-8');
153 return contents.includes(key) ? t : f;
154}
155
156function uniq(arr) {
157 return Array.from(new Set(arr));
158}
159
160function writeExtraEntry(name, {
161 cjs,
162 esm
163}, clean = true) {
164 if (clean) {
165 rimraf.sync(fromRoot(name));
166 }
167
168 mkdirp.sync(fromRoot(name));
169 const pkgJson = fromRoot(`${name}/package.json`);
170 const entryDir = fromRoot(name);
171 fs.writeFileSync(pkgJson, JSON.stringify({
172 main: path.relative(entryDir, cjs),
173 'jsnext:main': path.relative(entryDir, esm),
174 module: path.relative(entryDir, esm)
175 }, null, 2));
176}
177
178function hasLocalConfig(moduleName, searchOptions = {}) {
179 const explorerSync = cosmiconfigSync(moduleName, searchOptions);
180 const result = explorerSync.search(pkgPath);
181 return result !== null;
182}
183
184module.exports = {
185 appDirectory,
186 envIsSet,
187 fromRoot,
188 getConcurrentlyArgs,
189 hasFile,
190 hasLocalConfig,
191 hasPkgProp,
192 hasScript,
193 ifAnyDep,
194 ifDep,
195 ifDevDep,
196 ifFile,
197 ifPeerDep,
198 ifScript,
199 isOptedIn,
200 isOptedOut,
201 parseEnv,
202 pkg,
203 resolveBin,
204 resolveKcdScripts,
205 uniq,
206 writeExtraEntry
207};
\No newline at end of file