1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const tslib_1 = require("tslib");
|
4 | const path = require("path");
|
5 | const chalk_1 = require("chalk");
|
6 | const utils_fs_1 = require("@ionic/utils-fs");
|
7 | const app_1 = require("../../app");
|
8 | const git_1 = require("../../git");
|
9 | const config_1 = require("../../integrations/cordova/config");
|
10 | const project_1 = require("../../integrations/cordova/project");
|
11 | const npm_1 = require("../../utils/npm");
|
12 | const base_1 = require("./base");
|
13 | tslib_1.__exportStar(require("./base"), exports);
|
14 | tslib_1.__exportStar(require("./utils"), exports);
|
15 | class NpmInstalledLocally extends base_1.Ailment {
|
16 | constructor() {
|
17 | super(...arguments);
|
18 | this.id = 'npm-installed-locally';
|
19 | this.treatable = true;
|
20 | }
|
21 | getMessage() {
|
22 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
23 | return (`${chalk_1.default.bold('npm')} is installed locally.\n` +
|
24 | `${chalk_1.default.bold('npm')} is typically installed globally and may cause some confusion about versions when other CLIs use it.\n`).trim();
|
25 | });
|
26 | }
|
27 | detected() {
|
28 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
29 | const pkg = yield this.getLocalPackageJson('npm');
|
30 | return pkg !== undefined;
|
31 | });
|
32 | }
|
33 | getTreatmentSteps() {
|
34 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
35 | const [manager, ...managerArgs] = yield npm_1.pkgManagerArgs(this.config.get('npmClient'), { command: 'uninstall', pkg: 'npm' });
|
36 | return [
|
37 | {
|
38 | message: `Run: ${chalk_1.default.green(manager + ' ' + managerArgs.join(' '))}`,
|
39 | treat: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
40 | yield this.shell.run(manager, managerArgs, {});
|
41 | }),
|
42 | },
|
43 | ];
|
44 | });
|
45 | }
|
46 | }
|
47 | exports.NpmInstalledLocally = NpmInstalledLocally;
|
48 | class IonicCLIInstalledLocally extends base_1.Ailment {
|
49 | constructor() {
|
50 | super(...arguments);
|
51 | this.id = 'ionic-installed-locally';
|
52 | this.treatable = true;
|
53 | }
|
54 | getMessage() {
|
55 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
56 | return (`The Ionic CLI is installed locally.\n` +
|
57 | `While the CLI can run locally, there's no longer a reason to have it installed locally and it may cause some confusion over configuration and versions.\n`).trim();
|
58 | });
|
59 | }
|
60 | detected() {
|
61 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
62 | const pkg = yield this.getLocalPackageJson('ionic');
|
63 | return pkg !== undefined;
|
64 | });
|
65 | }
|
66 | getTreatmentSteps() {
|
67 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
68 | const [manager, ...managerArgs] = yield npm_1.pkgManagerArgs(this.config.get('npmClient'), { command: 'uninstall', pkg: 'ionic' });
|
69 | return [
|
70 | {
|
71 | message: `Run: ${chalk_1.default.green(manager + ' ' + managerArgs.join(' '))}`,
|
72 | treat: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
73 | yield this.shell.run(manager, managerArgs, {});
|
74 | }),
|
75 | },
|
76 | ];
|
77 | });
|
78 | }
|
79 | }
|
80 | exports.IonicCLIInstalledLocally = IonicCLIInstalledLocally;
|
81 | class GitNotUsed extends base_1.Ailment {
|
82 | constructor() {
|
83 | super(...arguments);
|
84 | this.id = 'git-not-used';
|
85 | }
|
86 | getMessage() {
|
87 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
88 | return (`Git doesn't appear to be in use.\n` +
|
89 | `We highly recommend using source control software such as git (${chalk_1.default.bold('https://git-scm.com')}) to track changes in your code throughout time.\n`).trim();
|
90 | });
|
91 | }
|
92 | detected() {
|
93 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
94 | if (!(yield git_1.isRepoInitialized(this.project.directory))) {
|
95 | return true;
|
96 | }
|
97 | const cmdInstalled = yield this.shell.cmdinfo('git', ['--version']);
|
98 | if (!cmdInstalled) {
|
99 | return true;
|
100 | }
|
101 | const [revListCount, status] = yield Promise.all([
|
102 | this.shell.output('git', ['rev-list', '--count', 'HEAD'], { fatalOnError: false, showCommand: false, showError: false }),
|
103 | this.shell.output('git', ['status', '--porcelain'], { fatalOnError: false, showCommand: false, showError: false }),
|
104 | ]);
|
105 | this.debug('rev-list count: %s, status: %s', revListCount.trim(), status);
|
106 | if (!revListCount) {
|
107 | return true;
|
108 | }
|
109 | const commitCount = Number(revListCount);
|
110 | const changes = Boolean(status);
|
111 | return commitCount === 1 && changes;
|
112 | });
|
113 | }
|
114 | getTreatmentSteps() {
|
115 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
116 | return [
|
117 | { message: `Download git if you don't have it installed: ${chalk_1.default.bold('https://git-scm.com/downloads')}` },
|
118 | { message: `Learn the basics if you're unfamiliar with git: ${chalk_1.default.bold('https://try.github.io')}` },
|
119 | { message: `Make your first commit and start tracking code changes! 😍` },
|
120 | ];
|
121 | });
|
122 | }
|
123 | }
|
124 | exports.GitNotUsed = GitNotUsed;
|
125 | class GitConfigInvalid extends base_1.Ailment {
|
126 | constructor() {
|
127 | super(...arguments);
|
128 | this.id = 'git-config-invalid';
|
129 | }
|
130 | getMessage() {
|
131 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
132 | const proId = yield this.project.requireProId();
|
133 | return (`App linked to ${chalk_1.default.bold(proId)} with invalid git configuration.\n` +
|
134 | `This app is linked to an app on Ionic (${chalk_1.default.bold(proId)}), but the git configuration is not valid.\n`).trim();
|
135 | });
|
136 | }
|
137 | detected() {
|
138 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
139 | const isLoggedIn = this.session.isLoggedIn();
|
140 | if (!isLoggedIn) {
|
141 | return false;
|
142 | }
|
143 | const proId = this.project.config.get('pro_id');
|
144 | if (!proId) {
|
145 | return false;
|
146 | }
|
147 | if (!(yield git_1.isRepoInitialized(this.project.directory))) {
|
148 | return false;
|
149 | }
|
150 | const remote = yield git_1.getIonicRemote({ shell: this.shell }, this.project.directory);
|
151 | if (!remote) {
|
152 | return true;
|
153 | }
|
154 | const token = this.session.getUserToken();
|
155 | const appClient = new app_1.AppClient({ token, client: this.client });
|
156 | const app = yield appClient.load(proId);
|
157 | if (app.repo_url !== remote) {
|
158 | return true;
|
159 | }
|
160 | return false;
|
161 | });
|
162 | }
|
163 | getTreatmentSteps() {
|
164 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
165 | return [
|
166 | { message: `Run: ${chalk_1.default.green('ionic git remote')}` },
|
167 | ];
|
168 | });
|
169 | }
|
170 | }
|
171 | exports.GitConfigInvalid = GitConfigInvalid;
|
172 | class IonicNativeOldVersionInstalled extends base_1.Ailment {
|
173 | constructor() {
|
174 | super(...arguments);
|
175 | this.id = 'ionic-native-old-version-installed';
|
176 | }
|
177 | getMessage() {
|
178 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
179 | return (`Old version of Ionic Native installed.\n` +
|
180 | `Ionic Native ${chalk_1.default.bold('ionic-native')} has been restructured into individual packages under the ${chalk_1.default.bold('@ionic-native/')} namespace to allow for better bundling and faster apps.\n`).trim();
|
181 | });
|
182 | }
|
183 | detected() {
|
184 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
185 | const pkg = yield this.getLocalPackageJson('ionic-native');
|
186 | return pkg !== undefined;
|
187 | });
|
188 | }
|
189 | getTreatmentSteps() {
|
190 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
191 | const args = yield npm_1.pkgManagerArgs(this.config.get('npmClient'), { command: 'uninstall', pkg: 'ionic-native' });
|
192 | return [
|
193 | { message: `Run ${chalk_1.default.green(args.join(' '))}` },
|
194 | { message: `Refer to ${chalk_1.default.bold('https://ionicframework.com/docs/native')} for installation & usage instructions` },
|
195 | ];
|
196 | });
|
197 | }
|
198 | }
|
199 | exports.IonicNativeOldVersionInstalled = IonicNativeOldVersionInstalled;
|
200 | class UnsavedCordovaPlatforms extends base_1.Ailment {
|
201 | constructor() {
|
202 | super(...arguments);
|
203 | this.id = 'unsaved-cordova-platforms';
|
204 | }
|
205 | getMessage() {
|
206 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
207 | return (`Cordova platforms unsaved.\n` +
|
208 | `There are Cordova platforms installed that are not saved in ${chalk_1.default.bold('config.xml')} or ${chalk_1.default.bold('package.json')}. It is good practice to manage Cordova platforms and their versions. See the Cordova docs${chalk_1.default.cyan('[1]')} for more information.\n\n` +
|
209 | `${chalk_1.default.cyan('[1]')}: ${chalk_1.default.bold('https://cordova.apache.org/docs/en/latest/platform_plugin_versioning_ref/')}\n`).trim();
|
210 | });
|
211 | }
|
212 | detected() {
|
213 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
214 | let cordova;
|
215 | try {
|
216 | cordova = yield this.project.getIntegration('cordova');
|
217 | }
|
218 | catch (e) {
|
219 | return false;
|
220 | }
|
221 | const platforms = yield project_1.getPlatforms(cordova.root);
|
222 | const conf = yield config_1.loadConfigXml({ project: this.project });
|
223 | const engines = conf.getPlatformEngines();
|
224 | const engineNames = new Set([...engines.map(e => e.name)]);
|
225 | const configXmlDiff = platforms.filter(p => !engineNames.has(p));
|
226 | return configXmlDiff.length > 0;
|
227 | });
|
228 | }
|
229 | getTreatmentSteps() {
|
230 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
231 | return [
|
232 | { message: `Run: ${chalk_1.default.green('ionic cordova platform save')}` },
|
233 | ];
|
234 | });
|
235 | }
|
236 | }
|
237 | exports.UnsavedCordovaPlatforms = UnsavedCordovaPlatforms;
|
238 | class DefaultCordovaBundleIdUsed extends base_1.Ailment {
|
239 | constructor() {
|
240 | super(...arguments);
|
241 | this.id = 'default-cordova-bundle-id-used';
|
242 | }
|
243 | getMessage() {
|
244 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
245 | return (`Package ID unchanged in ${chalk_1.default.bold('config.xml')}.\n` +
|
246 | `The Package Identifier (AKA "Bundle ID" for iOS and "Application ID" for Android) is a unique ID (usually written in reverse DNS notation, such as ${chalk_1.default.bold('com.mycompany.MyApp')}) that Cordova uses when compiling the native build of your app. When your app is submitted to the App Store or Play Store, the Package ID can't be changed. This issue was detected because this app's Package ID is ${chalk_1.default.green('"io.ionic.starter"')}, which is the default Package ID provided after running ${chalk_1.default.green('ionic start')}.`).trim();
|
247 | });
|
248 | }
|
249 | detected() {
|
250 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
251 | if (!this.project.config.get('integrations').cordova) {
|
252 | return false;
|
253 | }
|
254 | const conf = yield config_1.loadConfigXml({ project: this.project });
|
255 | return conf.getBundleId() === 'io.ionic.starter';
|
256 | });
|
257 | }
|
258 | getTreatmentSteps() {
|
259 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
260 | return [
|
261 | { message: `Change the ${chalk_1.default.bold('id')} attribute of ${chalk_1.default.bold('<widget>')} (root element) to something other than ${chalk_1.default.green('"io.ionic.starter"')}` },
|
262 | ];
|
263 | });
|
264 | }
|
265 | }
|
266 | exports.DefaultCordovaBundleIdUsed = DefaultCordovaBundleIdUsed;
|
267 | class ViewportFitNotSet extends base_1.Ailment {
|
268 | constructor() {
|
269 | super(...arguments);
|
270 | this.id = 'viewport-fit-not-set';
|
271 | }
|
272 | getMessage() {
|
273 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
274 | return (`${chalk_1.default.bold('viewport-fit=cover')} not set in ${chalk_1.default.bold('index.html')}\n` +
|
275 | `iOS 11 introduces new "safe regions" for webviews, which can throw off component sizing, squish the header into the status bar, letterbox the app on iPhone X, etc. Fixing this issue will ensure the webview takes up the full size of the screen. See ${chalk_1.default.bold('https://blog.ionicframework.com/ios-11-checklist')} for more information.`).trim();
|
276 | });
|
277 | }
|
278 | detected() {
|
279 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
280 | const indexHtml = yield utils_fs_1.readFile(path.resolve(yield this.project.getSourceDir(), 'index.html'), { encoding: 'utf8' });
|
281 | const m = indexHtml.match(/\<meta.*viewport-fit=cover/);
|
282 | return !Boolean(m);
|
283 | });
|
284 | }
|
285 | getTreatmentSteps() {
|
286 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
287 | return [
|
288 | { message: `Add ${chalk_1.default.bold('viewport-fit=cover')} to the ${chalk_1.default.bold('<meta name="viewport">')} tag in your ${chalk_1.default.bold('index.html')} file` },
|
289 | ];
|
290 | });
|
291 | }
|
292 | }
|
293 | exports.ViewportFitNotSet = ViewportFitNotSet;
|
294 | class CordovaPlatformsCommitted extends base_1.Ailment {
|
295 | constructor() {
|
296 | super(...arguments);
|
297 | this.id = 'cordova-platforms-committed';
|
298 | }
|
299 | getMessage() {
|
300 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
301 | return (`Cordova ${chalk_1.default.bold('platforms/')} directory is committed to git.\n` +
|
302 | `Cordova considers ${chalk_1.default.bold('platforms/')} and ${chalk_1.default.bold('plugins/')} build artifacts${chalk_1.default.cyan('[1]')}, and routinely overwrites files.\n\n` +
|
303 | `While committing these files might be necessary for some projects${chalk_1.default.cyan('[2]')}, generally platforms should be configured using ${chalk_1.default.bold('config.xml')} and Cordova hooks${chalk_1.default.cyan('[3]')} so that your project is more portable and SDK updates are easier.\n\n` +
|
304 | `${chalk_1.default.cyan('[1]')}: ${chalk_1.default.bold('https://cordova.apache.org/docs/en/latest/reference/cordova-cli/#version-control')}\n` +
|
305 | `${chalk_1.default.cyan('[2]')}: ${chalk_1.default.bold('https://cordova.apache.org/docs/en/latest/reference/cordova-cli/#platforms')}\n` +
|
306 | `${chalk_1.default.cyan('[3]')}: ${chalk_1.default.bold('https://cordova.apache.org/docs/en/latest/guide/appdev/hooks/index.html')}\n\n` +
|
307 | `${chalk_1.default.yellow(`${chalk_1.default.bold('WARNING')}: Attempting to fix this could be dangerous. Only proceed if you're sure you haven't made manual modifications to these files.`)}\n`).trim();
|
308 | });
|
309 | }
|
310 | detected() {
|
311 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
312 | if (!(yield git_1.isRepoInitialized(this.project.directory))) {
|
313 | return false;
|
314 | }
|
315 | const cmdInstalled = yield this.shell.cmdinfo('git', ['--version']);
|
316 | if (!cmdInstalled) {
|
317 | return false;
|
318 | }
|
319 | const files = (yield this.shell.output('git', ['ls-tree', '--name-only', 'HEAD'], { fatalOnError: false, showCommand: false, showError: false })).split('\n');
|
320 | return files.includes('platforms');
|
321 | });
|
322 | }
|
323 | getTreatmentSteps() {
|
324 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
325 | return [
|
326 | { message: `Remove ${chalk_1.default.bold('platforms/')} from source control: ${chalk_1.default.green('git rm -rf platforms/')} and ${chalk_1.default.green('git commit')}` },
|
327 | { message: `Make sure the ${chalk_1.default.bold('platforms/')} directory has been removed: ${chalk_1.default.green('rm -rf platforms/')}` },
|
328 | { message: `Allow Cordova to repopulate your platforms: ${chalk_1.default.green('ionic cordova prepare')}` },
|
329 | ];
|
330 | });
|
331 | }
|
332 | }
|
333 | exports.CordovaPlatformsCommitted = CordovaPlatformsCommitted;
|