-
Notifications
You must be signed in to change notification settings - Fork 642
/
index.ts
198 lines (160 loc) · 5.81 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import { BaseError, InputValidationError, PackageJson } from '@ionic/cli-framework';
import { readPackageJsonFile } from '@ionic/cli-framework/utils/node';
import { processExit } from '@ionic/utils-process';
import * as Debug from 'debug';
import * as path from 'path';
import { IonicNamespace } from './commands';
import { IPCMessage, IonicContext, IonicEnvironment } from './definitions';
import { isExitCodeException, isSuperAgentError } from './guards';
import { generateIonicEnvironment } from './lib';
import { failure, input, strong } from './lib/color';
import { Executor } from './lib/executor';
export * from './constants';
export * from './guards';
export * from './definitions';
const debug = Debug('ionic');
const PACKAGE_ROOT_PATH = __dirname;
const PACKAGE_JSON_PATH = path.resolve(PACKAGE_ROOT_PATH, 'package.json');
let _pkg: PackageJson | undefined;
let _executor: Executor | undefined;
async function loadPackageJson(): Promise<PackageJson> {
if (!_pkg) {
_pkg = await readPackageJsonFile(PACKAGE_JSON_PATH);
}
return _pkg;
}
export async function generateContext(): Promise<IonicContext> {
const pkg = await loadPackageJson();
if (!pkg.bin || !pkg.bin.ionic) {
throw new Error(`Missing "${strong('bin.ionic')}" in Ionic CLI package.json`);
}
if (!pkg.main) {
throw new Error(`Missing "${strong('main')}" in Ionic CLI package.json`);
}
return {
binPath: path.resolve(PACKAGE_ROOT_PATH, pkg.bin.ionic),
libPath: PACKAGE_ROOT_PATH,
execPath: process.cwd(),
version: pkg.version,
};
}
export async function loadExecutor(ctx: IonicContext, pargv: string[]): Promise<Executor> {
if (!_executor) {
const deps = await generateIonicEnvironment(ctx, pargv);
const namespace = new IonicNamespace(deps);
_executor = new Executor({ namespace });
}
return _executor;
}
async function authenticateFromEnvironment(ienv: IonicEnvironment) {
const token = process.env['IONIC_TOKEN'];
const email = process.env['IONIC_EMAIL'];
const password = process.env['IONIC_PASSWORD'];
if (token) {
const wasLoggedIn = ienv.session.isLoggedIn();
debug(`${strong('IONIC_TOKEN')} environment variable detected`);
if (ienv.config.get('tokens.user') !== token) {
debug(`${strong('IONIC_TOKEN')} mismatch with current session--attempting login`);
await ienv.session.tokenLogin(token);
if (wasLoggedIn) {
ienv.log.info(`You have been logged out--using ${strong('IONIC_TOKEN')} environment variable`);
}
}
} else if (email && password) {
debug(`${strong('IONIC_EMAIL')} / ${strong('IONIC_PASSWORD')} environment variables detected`);
if (ienv.config.get('user.email') !== email) {
debug(`${strong('IONIC_EMAIL')} mismatch with current session--attempting login`);
try {
await ienv.session.login(email, password);
} catch (e) {
ienv.log.error(`Error occurred during automatic login via ${strong('IONIC_EMAIL')} / ${strong('IONIC_PASSWORD')} environment variables.`);
throw e;
}
}
}
}
export async function run(pargv: string[]): Promise<void> {
let err: any;
let executor: Executor;
try {
executor = await loadExecutor(await generateContext(), pargv);
} catch (e) {
process.stderr.write(`${e.message ? e.message : (e.stack ? e.stack : e)}\n`);
process.exitCode = 1;
return;
}
const ienv = executor.namespace.env;
if (pargv[0] === '_') {
return;
}
try {
debug('Context: %o', ienv.ctx);
ienv.config.set('version', ienv.ctx.version);
const location = await executor.locate(pargv);
const [ , [ cmd = '' ] = [] ] = location.path;
if (!['config', 'completion', 'help', 'login', 'logout', 'version'].includes(cmd)) {
await authenticateFromEnvironment(ienv);
}
await executor.execute(location, process.env);
if (ienv.flags.interactive) {
const { runUpdateNotify } = await import('./lib/updates');
await runUpdateNotify(ienv, await loadPackageJson());
}
} catch (e) {
err = e;
}
if (err) {
process.exitCode = 1;
if (err instanceof InputValidationError) {
for (const e of err.errors) {
ienv.log.error(e.message);
}
ienv.log.msg(`Use the ${input('--help')} flag for more details.`);
} else if (isSuperAgentError(err)) {
const { formatSuperAgentError } = await import('./lib/http');
ienv.log.rawmsg(formatSuperAgentError(err));
} else if (err.code && err.code === 'ENOTFOUND' || err.code === 'ECONNREFUSED') {
ienv.log.error(
`Network connectivity error occurred, are you offline?\n` +
`If you are behind a firewall and need to configure proxy settings, see: ${strong('https://ion.link/cli-proxy-docs')}\n\n` +
failure(String(err.stack ? err.stack : err))
);
} else if (isExitCodeException(err)) {
if (err.message) {
if (err.exitCode > 0) {
ienv.log.error(err.message);
} else {
ienv.log.msg(err.message);
}
}
await processExit(err.exitCode);
} else if (err instanceof BaseError) {
ienv.log.error(err.message);
} else {
ienv.log.msg(failure(String(err.stack ? err.stack : err)));
if (err.stack) {
debug(failure(String(err.stack)));
}
}
}
}
export async function receive(msg: IPCMessage) {
if (!_executor) {
throw new Error('Executor not initialized.');
}
const { env, project } = _executor.namespace;
if (msg.type === 'telemetry') {
const { sendCommand } = await import('./lib/telemetry');
await sendCommand({
getInfo: env.getInfo,
client: env.client,
config: env.config,
ctx: env.ctx,
project,
session: env.session,
}, msg.data.command, msg.data.args);
} else if (msg.type === 'update-check') {
const { runUpdateCheck } = await import('./lib/updates');
await runUpdateCheck(env);
}
}