1 | import { readFile } from 'jsonfile';
|
2 | import Listr from 'listr';
|
3 | import pkgUp from 'pkg-up';
|
4 | import { v4 as uuid } from 'uuid';
|
5 |
|
6 | import GraphQLClient from './io/GraphQLClient';
|
7 | import checkForUpdates from './lib/checkForUpdates';
|
8 | import checkPackageJson from './lib/checkPackageJson';
|
9 | import getEnv from './lib/getEnv';
|
10 | import getOptions from './lib/getOptions';
|
11 | import { createLogger } from './lib/log';
|
12 | import NonTTYRenderer from './lib/NonTTYRenderer';
|
13 | import parseArgs from './lib/parseArgs';
|
14 | import getTasks from './tasks';
|
15 | import fatalError from './ui/messages/errors/fatalError';
|
16 | import fetchError from './ui/messages/errors/fetchError';
|
17 | import runtimeError from './ui/messages/errors/runtimeError';
|
18 | import taskError from './ui/messages/errors/taskError';
|
19 | import intro from './ui/messages/info/intro';
|
20 |
|
21 | export async function main(argv) {
|
22 | const sessionId = uuid();
|
23 | const env = getEnv();
|
24 | const log = createLogger(sessionId, env);
|
25 | const packagePath = await pkgUp();
|
26 | const packageJson = await readFile(packagePath);
|
27 |
|
28 |
|
29 |
|
30 | const ctx = { env, log, sessionId, packageJson, packagePath, ...parseArgs(argv) };
|
31 | await runAll(ctx);
|
32 |
|
33 | log.info('');
|
34 | process.exit(ctx.exitCode);
|
35 | }
|
36 |
|
37 | export async function runAll(ctx) {
|
38 |
|
39 | await Promise.all([runBuild(ctx), checkForUpdates(ctx)]);
|
40 |
|
41 | if (!ctx.exitCode || ctx.exitCode === 1) {
|
42 | await checkPackageJson(ctx);
|
43 | }
|
44 | }
|
45 |
|
46 | export async function runBuild(ctx) {
|
47 | ctx.log.info('');
|
48 | ctx.log.info(intro(ctx));
|
49 |
|
50 | try {
|
51 | ctx.options = await getOptions(ctx);
|
52 | } catch (e) {
|
53 | ctx.log.info('');
|
54 | ctx.log.error(e.message);
|
55 | ctx.exitCode = 254;
|
56 | return;
|
57 | }
|
58 |
|
59 | try {
|
60 | ctx.client = new GraphQLClient({
|
61 | uri: `${ctx.env.CHROMATIC_INDEX_URL}/graphql`,
|
62 | headers: {
|
63 | 'x-chromatic-session-id': ctx.sessionId,
|
64 | 'x-chromatic-cli-version': ctx.pkg.version,
|
65 | },
|
66 | retries: 3,
|
67 | log: ctx.log,
|
68 | });
|
69 |
|
70 | try {
|
71 | ctx.log.info('');
|
72 | if (ctx.options.interactive) ctx.log.queue();
|
73 | const options = ctx.options.interactive ? {} : { renderer: NonTTYRenderer, log: ctx.log };
|
74 | await new Listr(getTasks(ctx.options), options).run(ctx);
|
75 | } catch (err) {
|
76 | if (err.code === 'ECONNREFUSED' || err.name === 'StatusCodeError') {
|
77 | ctx.log.info('');
|
78 | ctx.log.error(fetchError(ctx, err));
|
79 | return;
|
80 | }
|
81 | try {
|
82 |
|
83 | err.message = taskError(ctx, err);
|
84 | } catch (ex) {
|
85 | const error = new Error(taskError(ctx, err));
|
86 | error.stack = err.stack;
|
87 | throw error;
|
88 | }
|
89 | throw err;
|
90 | } finally {
|
91 |
|
92 | const { runtimeErrors, runtimeWarnings } = ctx;
|
93 | if ((runtimeErrors && runtimeErrors.length) || (runtimeWarnings && runtimeWarnings.length)) {
|
94 | ctx.log.info('');
|
95 | ctx.log.error(runtimeError(ctx));
|
96 | }
|
97 |
|
98 | ctx.log.flush();
|
99 | if (ctx.stopApp) ctx.stopApp();
|
100 | if (ctx.closeTunnel) ctx.closeTunnel();
|
101 | }
|
102 | } catch (error) {
|
103 | const errors = [].concat(error);
|
104 |
|
105 | if (errors.length && !ctx.userError) {
|
106 | ctx.log.info('');
|
107 | ctx.log.error(fatalError(ctx, errors));
|
108 | }
|
109 |
|
110 |
|
111 | if (!ctx.exitCode) ctx.exitCode = 255;
|
112 | }
|
113 | }
|