1 | "use strict";
|
2 |
|
3 | const fs = require('fs');
|
4 |
|
5 | const path = require('path');
|
6 |
|
7 | const rimraf = require('rimraf');
|
8 |
|
9 | const mkdirp = require('mkdirp');
|
10 |
|
11 | const arrify = require('arrify');
|
12 |
|
13 | const has = require('lodash.has');
|
14 |
|
15 | const readPkgUp = require('read-pkg-up');
|
16 |
|
17 | const which = require('which');
|
18 |
|
19 | const {
|
20 | cosmiconfigSync
|
21 | } = require('cosmiconfig');
|
22 |
|
23 | const {
|
24 | packageJson: pkg,
|
25 | path: pkgPath
|
26 | } = readPkgUp.sync({
|
27 | cwd: fs.realpathSync(process.cwd())
|
28 | });
|
29 | const appDirectory = path.dirname(pkgPath);
|
30 |
|
31 | function resolveKcdScripts() {
|
32 | if (pkg.name === 'kcd-scripts') {
|
33 | return require.resolve('./').replace(process.cwd(), '.');
|
34 | }
|
35 |
|
36 | return resolveBin('kcd-scripts');
|
37 | }
|
38 |
|
39 |
|
40 | function 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) {
|
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 |
|
78 | const fromRoot = (...p) => path.join(appDirectory, ...p);
|
79 |
|
80 | const hasFile = (...p) => fs.existsSync(fromRoot(...p));
|
81 |
|
82 | const ifFile = (files, t, f) => arrify(files).some(file => hasFile(file)) ? t : f;
|
83 |
|
84 | const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop));
|
85 |
|
86 | const hasPkgSubProp = pkgProp => props => hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`));
|
87 |
|
88 | const ifPkgSubProp = pkgProp => (props, t, f) => hasPkgSubProp(pkgProp)(props) ? t : f;
|
89 |
|
90 | const hasScript = hasPkgSubProp('scripts');
|
91 | const hasPeerDep = hasPkgSubProp('peerDependencies');
|
92 | const hasDep = hasPkgSubProp('dependencies');
|
93 | const hasDevDep = hasPkgSubProp('devDependencies');
|
94 |
|
95 | const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args));
|
96 |
|
97 | const ifPeerDep = ifPkgSubProp('peerDependencies');
|
98 | const ifDep = ifPkgSubProp('dependencies');
|
99 | const ifDevDep = ifPkgSubProp('devDependencies');
|
100 |
|
101 | const ifAnyDep = (deps, t, f) => hasAnyDep(arrify(deps)) ? t : f;
|
102 |
|
103 | const ifScript = ifPkgSubProp('scripts');
|
104 |
|
105 | function 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 |
|
117 | function envIsSet(name) {
|
118 | return process.env.hasOwnProperty(name) && process.env[name] && process.env[name] !== 'undefined';
|
119 | }
|
120 |
|
121 | function 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(',');
|
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))
|
135 | ].filter(Boolean);
|
136 | }
|
137 |
|
138 | function 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 |
|
147 | function 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 |
|
156 | function uniq(arr) {
|
157 | return Array.from(new Set(arr));
|
158 | }
|
159 |
|
160 | function 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 |
|
178 | function hasLocalConfig(moduleName, searchOptions = {}) {
|
179 | const explorerSync = cosmiconfigSync(moduleName, searchOptions);
|
180 | const result = explorerSync.search(pkgPath);
|
181 | return result !== null;
|
182 | }
|
183 |
|
184 | module.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 |