react-native-update-cli 1.44.2 → 1.44.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/utils/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import pkg from '../../package.json';
|
|
|
5
5
|
import AppInfoParser from './app-info-parser';
|
|
6
6
|
import semverSatisfies from 'semver/functions/satisfies';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
|
-
import latestVersion from '
|
|
8
|
+
import latestVersion from '../utils/latest-version';
|
|
9
9
|
import { checkPlugins } from './check-plugin';
|
|
10
10
|
|
|
11
11
|
import { read } from 'read';
|
|
@@ -98,7 +98,7 @@ export async function getAppInfo(fn: string) {
|
|
|
98
98
|
const metaJsonFile = await appInfoParser.parser.getEntryFromHarmonyApp(
|
|
99
99
|
/rawfile\/meta.json/,
|
|
100
100
|
);
|
|
101
|
-
let metaData = {};
|
|
101
|
+
let metaData: Record<string, any> = {};
|
|
102
102
|
if (metaJsonFile) {
|
|
103
103
|
metaData = JSON.parse(metaJsonFile.toString());
|
|
104
104
|
}
|
|
@@ -181,16 +181,13 @@ export async function printVersionCommand() {
|
|
|
181
181
|
version: chalk.green(latestRnuCliVersion),
|
|
182
182
|
})}`
|
|
183
183
|
: '';
|
|
184
|
-
console.log(
|
|
185
|
-
|
|
186
|
-
);
|
|
187
|
-
let rnuVersion = '';
|
|
188
|
-
rnuVersion = depVersions['react-native-update'];
|
|
189
|
-
latestRnuVersion = latestRnuVersion
|
|
190
|
-
? ` ${t('latestVersionTag', { version: chalk.green(latestRnuVersion) })}`
|
|
191
|
-
: '';
|
|
192
|
-
console.log(`react-native-update: ${rnuVersion}${latestRnuVersion}`);
|
|
184
|
+
console.log(`react-native-update-cli: ${pkg.version}${latestRnuCliVersion}`);
|
|
185
|
+
const rnuVersion = depVersions['react-native-update'];
|
|
193
186
|
if (rnuVersion) {
|
|
187
|
+
latestRnuVersion = latestRnuVersion
|
|
188
|
+
? ` ${t('latestVersionTag', { version: chalk.green(latestRnuVersion) })}`
|
|
189
|
+
: '';
|
|
190
|
+
console.log(`react-native-update: ${rnuVersion}${latestRnuVersion}`);
|
|
194
191
|
if (IS_CRESC) {
|
|
195
192
|
if (semverSatisfies(rnuVersion, '<10.27.0')) {
|
|
196
193
|
console.error(
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import {
|
|
2
|
+
blue,
|
|
3
|
+
bold,
|
|
4
|
+
cyan,
|
|
5
|
+
gray,
|
|
6
|
+
green,
|
|
7
|
+
italic,
|
|
8
|
+
magenta,
|
|
9
|
+
red,
|
|
10
|
+
reset,
|
|
11
|
+
strip,
|
|
12
|
+
underline,
|
|
13
|
+
yellow,
|
|
14
|
+
} from '@colors/colors/safe';
|
|
15
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
16
|
+
import { dirname } from 'node:path';
|
|
17
|
+
import latestVersion, {
|
|
18
|
+
type Package,
|
|
19
|
+
type PackageJson,
|
|
20
|
+
type LatestVersionPackage,
|
|
21
|
+
type LatestVersionOptions,
|
|
22
|
+
} from '.';
|
|
23
|
+
import semverMajor from 'semver/functions/major';
|
|
24
|
+
import semverDiff from 'semver/functions/diff';
|
|
25
|
+
|
|
26
|
+
interface TableColumn {
|
|
27
|
+
label: string;
|
|
28
|
+
attrName: keyof TableRow;
|
|
29
|
+
align: 'left' | 'center' | 'right';
|
|
30
|
+
maxLength: number;
|
|
31
|
+
items: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type TableRowGroup =
|
|
35
|
+
| 'patch'
|
|
36
|
+
| 'minor'
|
|
37
|
+
| 'major'
|
|
38
|
+
| 'majorVersionZero'
|
|
39
|
+
| 'unknown';
|
|
40
|
+
|
|
41
|
+
interface TableRow {
|
|
42
|
+
name: string;
|
|
43
|
+
location: string;
|
|
44
|
+
installed: string;
|
|
45
|
+
tagOrRange: string;
|
|
46
|
+
separator: string;
|
|
47
|
+
wanted: string;
|
|
48
|
+
latest: string;
|
|
49
|
+
group: TableRowGroup;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const colorizeDiff = (from: string, to: string): string => {
|
|
53
|
+
const toParts = to.split('.');
|
|
54
|
+
|
|
55
|
+
const diffIndex = from.split('.').findIndex((part, i) => part !== toParts[i]);
|
|
56
|
+
if (diffIndex !== -1) {
|
|
57
|
+
let color = magenta;
|
|
58
|
+
if (toParts[0] !== '0') {
|
|
59
|
+
color = diffIndex === 0 ? red : diffIndex === 1 ? cyan : green;
|
|
60
|
+
}
|
|
61
|
+
const start = toParts.slice(0, diffIndex).join('.');
|
|
62
|
+
const mid = diffIndex === 0 ? '' : '.';
|
|
63
|
+
const end = color(toParts.slice(diffIndex).join('.'));
|
|
64
|
+
return `${start}${mid}${end}`;
|
|
65
|
+
}
|
|
66
|
+
return to;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const columnCellRenderer = (column: TableColumn, row: TableRow): string => {
|
|
70
|
+
let text = row[column.attrName];
|
|
71
|
+
const gap =
|
|
72
|
+
text.length < column.maxLength
|
|
73
|
+
? ' '.repeat(column.maxLength - text.length)
|
|
74
|
+
: '';
|
|
75
|
+
|
|
76
|
+
switch (column.attrName) {
|
|
77
|
+
case 'name':
|
|
78
|
+
text = yellow(text);
|
|
79
|
+
break;
|
|
80
|
+
case 'installed':
|
|
81
|
+
case 'separator':
|
|
82
|
+
text = blue(text);
|
|
83
|
+
break;
|
|
84
|
+
case 'location':
|
|
85
|
+
case 'tagOrRange':
|
|
86
|
+
text = gray(text);
|
|
87
|
+
break;
|
|
88
|
+
case 'wanted':
|
|
89
|
+
text = colorizeDiff(row.installed, text);
|
|
90
|
+
break;
|
|
91
|
+
case 'latest':
|
|
92
|
+
if (text !== row.wanted) {
|
|
93
|
+
text = colorizeDiff(row.installed, text);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return column.align === 'right' ? `${gap}${text}` : `${text}${gap}`;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const columnHeaderRenderer = (column: TableColumn): string => {
|
|
104
|
+
const text = column.label;
|
|
105
|
+
const gap =
|
|
106
|
+
text.length < column.maxLength
|
|
107
|
+
? ' '.repeat(column.maxLength - text.length)
|
|
108
|
+
: '';
|
|
109
|
+
return column.align === 'right'
|
|
110
|
+
? `${gap}${underline(text)}`
|
|
111
|
+
: `${underline(text)}${gap}`;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const drawBox = (
|
|
115
|
+
lines: string[],
|
|
116
|
+
color = yellow,
|
|
117
|
+
horizontalPadding = 3,
|
|
118
|
+
): void => {
|
|
119
|
+
const maxLineWidth = lines.reduce(
|
|
120
|
+
(max, row) => Math.max(max, strip(row).length),
|
|
121
|
+
0,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
console.log(color(`┌${'─'.repeat(maxLineWidth + horizontalPadding * 2)}┐`));
|
|
125
|
+
lines.forEach((row) => {
|
|
126
|
+
const padding = ' '.repeat(horizontalPadding);
|
|
127
|
+
const fullRow = `${row}${' '.repeat(maxLineWidth - strip(row).length)}`;
|
|
128
|
+
console.log(
|
|
129
|
+
`${color('│')}${padding}${reset(fullRow)}${padding}${color('│')}`,
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
console.log(color(`└${'─'.repeat(maxLineWidth + horizontalPadding * 2)}┘`));
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const getTableColumns = (rows: TableRow[]): TableColumn[] => {
|
|
136
|
+
const columns: TableColumn[] = [
|
|
137
|
+
{
|
|
138
|
+
label: 'Package',
|
|
139
|
+
attrName: 'name',
|
|
140
|
+
align: 'left',
|
|
141
|
+
maxLength: 0,
|
|
142
|
+
items: [],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: 'Location',
|
|
146
|
+
attrName: 'location',
|
|
147
|
+
align: 'left',
|
|
148
|
+
maxLength: 0,
|
|
149
|
+
items: [],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
label: 'Installed',
|
|
153
|
+
attrName: 'installed',
|
|
154
|
+
align: 'right',
|
|
155
|
+
maxLength: 0,
|
|
156
|
+
items: [],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
label: '',
|
|
160
|
+
attrName: 'separator',
|
|
161
|
+
align: 'center',
|
|
162
|
+
maxLength: 0,
|
|
163
|
+
items: [],
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
label: 'Range',
|
|
167
|
+
attrName: 'tagOrRange',
|
|
168
|
+
align: 'right',
|
|
169
|
+
maxLength: 0,
|
|
170
|
+
items: [],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
label: '',
|
|
174
|
+
attrName: 'separator',
|
|
175
|
+
align: 'center',
|
|
176
|
+
maxLength: 0,
|
|
177
|
+
items: [],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
label: 'Wanted',
|
|
181
|
+
attrName: 'wanted',
|
|
182
|
+
align: 'right',
|
|
183
|
+
maxLength: 0,
|
|
184
|
+
items: [],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
label: 'Latest',
|
|
188
|
+
attrName: 'latest',
|
|
189
|
+
align: 'right',
|
|
190
|
+
maxLength: 0,
|
|
191
|
+
items: [],
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
rows.forEach((row) => {
|
|
195
|
+
columns.forEach((column) => {
|
|
196
|
+
column.maxLength = Math.max(
|
|
197
|
+
column.label.length,
|
|
198
|
+
column.maxLength,
|
|
199
|
+
row[column.attrName].length || 0,
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
return columns;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const getTableRows = (updates: LatestVersionPackage[]): TableRow[] => {
|
|
207
|
+
return updates.reduce<TableRow[]>((all, pkg) => {
|
|
208
|
+
const {
|
|
209
|
+
name,
|
|
210
|
+
latest,
|
|
211
|
+
local,
|
|
212
|
+
globalNpm,
|
|
213
|
+
globalYarn,
|
|
214
|
+
wantedTagOrRange,
|
|
215
|
+
updatesAvailable,
|
|
216
|
+
} = pkg;
|
|
217
|
+
const getGroup = (a?: string, b?: string): TableRowGroup => {
|
|
218
|
+
if (b && semverMajor(b) === 0) {
|
|
219
|
+
return 'majorVersionZero';
|
|
220
|
+
} else if (a && b) {
|
|
221
|
+
const releaseType = semverDiff(a, b) ?? '';
|
|
222
|
+
if (['major', 'premajor', 'prerelease'].includes(releaseType)) {
|
|
223
|
+
return 'major';
|
|
224
|
+
} else if (['minor', 'preminor'].includes(releaseType)) {
|
|
225
|
+
return 'minor';
|
|
226
|
+
} else if (['patch', 'prepatch'].includes(releaseType)) {
|
|
227
|
+
return 'patch';
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return 'unknown';
|
|
231
|
+
};
|
|
232
|
+
const add = (
|
|
233
|
+
group: TableRowGroup,
|
|
234
|
+
location: string,
|
|
235
|
+
installed?: string,
|
|
236
|
+
wanted?: string,
|
|
237
|
+
) =>
|
|
238
|
+
all.push({
|
|
239
|
+
name: ' ' + name,
|
|
240
|
+
location,
|
|
241
|
+
installed: installed ?? 'unknown',
|
|
242
|
+
latest: latest ?? 'unknown',
|
|
243
|
+
tagOrRange: wantedTagOrRange ?? 'unknown',
|
|
244
|
+
separator: '→',
|
|
245
|
+
wanted: wanted ?? 'unknown',
|
|
246
|
+
group,
|
|
247
|
+
});
|
|
248
|
+
if (updatesAvailable) {
|
|
249
|
+
if (updatesAvailable.local) {
|
|
250
|
+
add(
|
|
251
|
+
getGroup(local, updatesAvailable.local),
|
|
252
|
+
'local',
|
|
253
|
+
local,
|
|
254
|
+
updatesAvailable.local,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
if (updatesAvailable.globalNpm) {
|
|
258
|
+
add(
|
|
259
|
+
getGroup(globalNpm, updatesAvailable.globalNpm),
|
|
260
|
+
'NPM global',
|
|
261
|
+
globalNpm,
|
|
262
|
+
updatesAvailable.globalNpm,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
if (updatesAvailable.globalYarn) {
|
|
266
|
+
add(
|
|
267
|
+
getGroup(globalYarn, updatesAvailable.globalYarn),
|
|
268
|
+
'YARN global',
|
|
269
|
+
globalYarn,
|
|
270
|
+
updatesAvailable.globalYarn,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
if (local && local !== latest) {
|
|
275
|
+
add(getGroup(local, latest), 'local', local, pkg.wanted);
|
|
276
|
+
}
|
|
277
|
+
if (globalNpm && globalNpm !== latest) {
|
|
278
|
+
add(getGroup(globalNpm, latest), 'NPM global', globalNpm, pkg.wanted);
|
|
279
|
+
}
|
|
280
|
+
if (globalYarn && globalYarn !== latest) {
|
|
281
|
+
add(
|
|
282
|
+
getGroup(globalYarn, latest),
|
|
283
|
+
'YARN global',
|
|
284
|
+
globalYarn,
|
|
285
|
+
pkg.wanted,
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
if (!local && !globalNpm && !globalYarn) {
|
|
289
|
+
add('unknown', 'unknown', 'unknown', pkg.wanted);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return all;
|
|
293
|
+
}, []);
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
const displayTable = (latestVersionPackages: LatestVersionPackage[]): void => {
|
|
297
|
+
const updates = latestVersionPackages.filter((pkg) => pkg.updatesAvailable);
|
|
298
|
+
if (updates.length) {
|
|
299
|
+
const rows = getTableRows(updates);
|
|
300
|
+
const hasUpdates = rows.some((row) => row.installed !== 'unknown');
|
|
301
|
+
const columns = getTableColumns(rows);
|
|
302
|
+
const columnGap = 2;
|
|
303
|
+
|
|
304
|
+
const getGroupLines = (
|
|
305
|
+
groupType: TableRowGroup,
|
|
306
|
+
color: (str: string) => string,
|
|
307
|
+
title: string,
|
|
308
|
+
description?: string,
|
|
309
|
+
): string[] => {
|
|
310
|
+
const items = rows
|
|
311
|
+
.filter((row) => row.group === groupType)
|
|
312
|
+
.sort((a, b) => (a.name > b.name ? 1 : -1));
|
|
313
|
+
return !items.length
|
|
314
|
+
? []
|
|
315
|
+
: [
|
|
316
|
+
'',
|
|
317
|
+
color(`${bold(title)} ${italic(`(${description})`)}`),
|
|
318
|
+
...items.map((row) =>
|
|
319
|
+
columns
|
|
320
|
+
.map((column) => columnCellRenderer(column, row))
|
|
321
|
+
.join(' '.repeat(columnGap)),
|
|
322
|
+
),
|
|
323
|
+
];
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
327
|
+
drawBox(
|
|
328
|
+
[
|
|
329
|
+
'',
|
|
330
|
+
hasUpdates ? yellow('Important updates are available.') : undefined,
|
|
331
|
+
hasUpdates ? '' : undefined,
|
|
332
|
+
columns.map(columnHeaderRenderer).join(' '.repeat(columnGap)),
|
|
333
|
+
...getGroupLines(
|
|
334
|
+
'patch',
|
|
335
|
+
green,
|
|
336
|
+
'Patch',
|
|
337
|
+
'backwards-compatible bug fixes',
|
|
338
|
+
),
|
|
339
|
+
...getGroupLines(
|
|
340
|
+
'minor',
|
|
341
|
+
cyan,
|
|
342
|
+
'Minor',
|
|
343
|
+
'backwards-compatible features',
|
|
344
|
+
),
|
|
345
|
+
...getGroupLines(
|
|
346
|
+
'major',
|
|
347
|
+
red,
|
|
348
|
+
'Major',
|
|
349
|
+
'potentially breaking API changes',
|
|
350
|
+
),
|
|
351
|
+
...getGroupLines(
|
|
352
|
+
'majorVersionZero',
|
|
353
|
+
magenta,
|
|
354
|
+
'Major version zero',
|
|
355
|
+
'not stable, anything may change',
|
|
356
|
+
),
|
|
357
|
+
...getGroupLines('unknown', blue, 'Missing', 'not installed'),
|
|
358
|
+
'',
|
|
359
|
+
].filter((line) => line !== undefined) as string[],
|
|
360
|
+
);
|
|
361
|
+
} else {
|
|
362
|
+
console.log(green('🎉 Packages are up-to-date'));
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const checkVersions = async (
|
|
367
|
+
packages: Package | Package[] | PackageJson,
|
|
368
|
+
skipMissing: boolean,
|
|
369
|
+
options: LatestVersionOptions = { useCache: true },
|
|
370
|
+
): Promise<void> => {
|
|
371
|
+
const ora = (await import('ora')).default;
|
|
372
|
+
const spinner = ora({ text: cyan('Checking versions...') });
|
|
373
|
+
spinner.start();
|
|
374
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
375
|
+
// @ts-ignore
|
|
376
|
+
let latestVersionPackages: LatestVersionPackage[] = await latestVersion(
|
|
377
|
+
packages,
|
|
378
|
+
options,
|
|
379
|
+
);
|
|
380
|
+
if (skipMissing) {
|
|
381
|
+
latestVersionPackages = latestVersionPackages.filter(
|
|
382
|
+
(pkg) => pkg.local ?? pkg.globalNpm ?? pkg.globalYarn,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
spinner.stop();
|
|
386
|
+
displayTable(latestVersionPackages);
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
void (async () => {
|
|
390
|
+
let args = process.argv.slice(2);
|
|
391
|
+
|
|
392
|
+
const skipMissing = args.includes('--skip-missing');
|
|
393
|
+
|
|
394
|
+
// Remove any options from the arguments
|
|
395
|
+
args = args.filter((arg) => !arg.startsWith('-'));
|
|
396
|
+
|
|
397
|
+
// If argument is a package.json file
|
|
398
|
+
if (args.length === 1 && args[0].endsWith('package.json')) {
|
|
399
|
+
if (existsSync(args[0])) {
|
|
400
|
+
process.chdir(dirname(args[0]));
|
|
401
|
+
await checkVersions(
|
|
402
|
+
JSON.parse(readFileSync(args[0]).toString()) as PackageJson,
|
|
403
|
+
skipMissing,
|
|
404
|
+
);
|
|
405
|
+
} else {
|
|
406
|
+
console.log(cyan('No package.json file were found'));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// else..
|
|
410
|
+
else {
|
|
411
|
+
// Check if a local package.json file exists
|
|
412
|
+
let localPkgJson: PackageJson | undefined;
|
|
413
|
+
if (existsSync('package.json')) {
|
|
414
|
+
localPkgJson = JSON.parse(readFileSync('package.json').toString());
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Check given arguments
|
|
418
|
+
if (args.length) {
|
|
419
|
+
// Map arguments with any range that could be found in local package.json
|
|
420
|
+
args = args.map((arg) => {
|
|
421
|
+
if (localPkgJson?.dependencies?.[arg]) {
|
|
422
|
+
return `${arg}@${localPkgJson.dependencies?.[arg]}`;
|
|
423
|
+
}
|
|
424
|
+
if (localPkgJson?.devDependencies?.[arg]) {
|
|
425
|
+
return `${arg}@${localPkgJson.devDependencies?.[arg]}`;
|
|
426
|
+
}
|
|
427
|
+
if (localPkgJson?.peerDependencies?.[arg]) {
|
|
428
|
+
return `${arg}@${localPkgJson.peerDependencies?.[arg]}`;
|
|
429
|
+
}
|
|
430
|
+
return arg;
|
|
431
|
+
});
|
|
432
|
+
await checkVersions(args, skipMissing);
|
|
433
|
+
}
|
|
434
|
+
// ...else check the local package.json if any
|
|
435
|
+
else if (localPkgJson) {
|
|
436
|
+
await checkVersions(localPkgJson, skipMissing);
|
|
437
|
+
}
|
|
438
|
+
// ...else do nothing
|
|
439
|
+
else {
|
|
440
|
+
console.log(cyan('No packages were found'));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
})();
|