1 |
|
2 |
|
3 | const program = require('commander');
|
4 |
|
5 | const { promisify } = require('util');
|
6 | const glob = promisify(require('glob'));
|
7 | const { outputFile, readFile, readJson, pathExists } = require('fs-extra');
|
8 | const inquirer = require('inquirer');
|
9 | const Promise = require('bluebird');
|
10 |
|
11 | const addStamp = require('./util/addStamp');
|
12 | const addHash = require('./util/addHash');
|
13 | const generateHash = require('./util/generateHash');
|
14 | const getHashDiff = require('./util/getHashDiff');
|
15 | const logger = require('./util/logger');
|
16 | const { version } = require('../package.json');
|
17 | const { NO_MATCHING_FILES, EMDAER_FAILED } = require('./errors');
|
18 |
|
19 | module.exports = async function cli(
|
20 | emdaer,
|
21 | args = process.argv
|
22 | ) {
|
23 | let exitCode = 0;
|
24 | program
|
25 | .version(version)
|
26 | .option(
|
27 | '-p, --path <glob>',
|
28 | 'globbed path in which to search for emdaer files.'
|
29 | )
|
30 | .option('-y, --yes', 'answer "yes" too all prompts')
|
31 | .parse(args);
|
32 |
|
33 | const globPath = '.emdaer/**/*.emdaer.md';
|
34 | let origins = [];
|
35 | if (program.args.length > 0) {
|
36 | (await Promise.all(program.args.map(pathExists))).forEach(
|
37 | (exists, index) => {
|
38 | if (!exists) {
|
39 | logger.warn(NO_MATCHING_FILES(program.args[index]));
|
40 | } else {
|
41 | origins.push(program.args[index]);
|
42 | }
|
43 | }
|
44 | );
|
45 | } else {
|
46 | origins = await glob(globPath);
|
47 | }
|
48 | const { name } = await readJson('package.json');
|
49 | if (!origins.length) {
|
50 | logger.warn(
|
51 | NO_MATCHING_FILES(
|
52 | program.args.length ? program.args.join(', ') : globPath
|
53 | )
|
54 | );
|
55 | } else {
|
56 | try {
|
57 | const filesMeta = await Promise.mapSeries(origins, async origin => {
|
58 | let skip = false;
|
59 | const [, basePath, fileName, fileExtension] = origin.match(
|
60 | /(.*)\.emdaer\/(.*)\.emdaer(\.md)/
|
61 | );
|
62 | const destination = `${basePath}${fileName}${fileExtension}`;
|
63 | const [storedHash, existingContentHash] = await getHashDiff(
|
64 | destination
|
65 | );
|
66 | const diff = storedHash !== existingContentHash;
|
67 | if (diff && !program.yes) {
|
68 | const { overwrite } = await inquirer.prompt({
|
69 | name: 'overwrite',
|
70 | type: 'confirm',
|
71 | default: 'n',
|
72 | message: `it appears ${fileName}${fileExtension} has been changed. You may want to move changes you made manually to ${fileName}.emdaer${fileExtension} instead.\nWould you like to overwrite the contents of ${fileName}${fileExtension}?`
|
73 | });
|
74 | skip = !overwrite;
|
75 | }
|
76 | return {
|
77 | origin,
|
78 | destination,
|
79 | diff,
|
80 | storedHash,
|
81 | existingContentHash,
|
82 | skip,
|
83 | };
|
84 | });
|
85 | await Promise.map(
|
86 | filesMeta,
|
87 | async ({ origin, destination, diff, storedHash, skip }) => {
|
88 | if (skip) {
|
89 | logger.warn(`skipping ${destination} for ${name} ↩️`);
|
90 | return Promise.resolve();
|
91 | }
|
92 | const re = await readFile(origin);
|
93 | const contents = await emdaer(origin, re.toString());
|
94 | const newHash = generateHash(contents);
|
95 | if (newHash === storedHash && !diff) {
|
96 | logger.warn(
|
97 | `no changes for ${destination} for ${name}. skipping ↩️`
|
98 | );
|
99 | return Promise.resolve();
|
100 | }
|
101 | logger.log(`writing ${destination} for ${name} 👌`);
|
102 | return outputFile(
|
103 | destination,
|
104 | await addStamp(await addHash(contents), origin)
|
105 | );
|
106 | }
|
107 | );
|
108 | } catch (e) {
|
109 | logger.error(`${EMDAER_FAILED}\n${e}`);
|
110 | exitCode = 1;
|
111 | }
|
112 | }
|
113 | return exitCode;
|
114 | };
|