react-native-update-cli 2.8.5 → 2.9.1
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/lib/api.d.ts +18 -0
- package/lib/app.d.ts +38 -0
- package/lib/app.js +5 -4
- package/lib/bundle-pack.d.ts +1 -0
- package/lib/bundle-pack.js +104 -0
- package/lib/bundle-runner.d.ts +20 -0
- package/lib/bundle-runner.js +404 -0
- package/lib/bundle.d.ts +6 -0
- package/lib/bundle.js +73 -471
- package/lib/diff.d.ts +13 -0
- package/lib/diff.js +144 -123
- package/lib/exports.d.ts +12 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -13
- package/lib/install.d.ts +4 -0
- package/lib/locales/en.d.ts +137 -0
- package/lib/locales/zh.d.ts +136 -0
- package/lib/module-manager.d.ts +20 -0
- package/lib/module-manager.js +3 -9
- package/lib/modules/app-module.d.ts +2 -0
- package/lib/modules/app-module.js +84 -44
- package/lib/modules/bundle-module.d.ts +2 -0
- package/lib/modules/bundle-module.js +7 -8
- package/lib/modules/index.d.ts +6 -0
- package/lib/modules/package-module.d.ts +2 -0
- package/lib/modules/user-module.d.ts +2 -0
- package/lib/modules/user-module.js +55 -44
- package/lib/modules/version-module.d.ts +2 -0
- package/lib/package.d.ts +59 -0
- package/lib/package.js +110 -139
- package/lib/provider.d.ts +26 -0
- package/lib/provider.js +115 -217
- package/lib/types.d.ts +120 -0
- package/lib/user.d.ts +8 -0
- package/lib/utils/add-gitignore.d.ts +1 -0
- package/lib/utils/app-info-parser/aab.d.ts +22 -0
- package/lib/utils/app-info-parser/aab.js +0 -4
- package/lib/utils/app-info-parser/apk.d.ts +14 -0
- package/lib/utils/app-info-parser/apk.js +6 -4
- package/lib/utils/app-info-parser/app.d.ts +4 -0
- package/lib/utils/app-info-parser/app.js +3 -0
- package/lib/utils/app-info-parser/index.d.ts +16 -0
- package/lib/utils/app-info-parser/index.js +2 -0
- package/lib/utils/app-info-parser/ipa.d.ts +14 -0
- package/lib/utils/app-info-parser/ipa.js +1 -1
- package/lib/utils/app-info-parser/resource-finder.d.ts +49 -0
- package/lib/utils/app-info-parser/utils.d.ts +31 -0
- package/lib/utils/app-info-parser/utils.js +1 -0
- package/lib/utils/app-info-parser/xml-parser/binary.d.ts +56 -0
- package/lib/utils/app-info-parser/xml-parser/manifest.d.ts +10 -0
- package/lib/utils/app-info-parser/zip.d.ts +18 -0
- package/lib/utils/app-info-parser/zip.js +7 -9
- package/lib/utils/check-lockfile.d.ts +1 -0
- package/lib/utils/check-plugin.d.ts +7 -0
- package/lib/utils/command-result.d.ts +3 -0
- package/lib/utils/command-result.js +35 -0
- package/lib/utils/constants.d.ts +9 -0
- package/lib/utils/dep-versions.d.ts +1 -0
- package/lib/utils/git.d.ts +8 -0
- package/lib/utils/http-helper.d.ts +4 -0
- package/lib/utils/i18n.d.ts +12 -0
- package/lib/utils/index.d.ts +22 -0
- package/lib/utils/index.js +52 -22
- package/lib/utils/latest-version/cli.d.ts +1 -0
- package/lib/utils/latest-version/cli.js +24 -60
- package/lib/utils/latest-version/index.d.ts +146 -0
- package/lib/utils/latest-version/index.js +22 -22
- package/lib/utils/options.d.ts +4 -0
- package/lib/utils/options.js +63 -0
- package/lib/utils/plugin-config.d.ts +9 -0
- package/lib/utils/zip-entries.d.ts +3 -0
- package/lib/versions.d.ts +43 -0
- package/lib/workflow-runner.d.ts +2 -0
- package/lib/workflow-runner.js +25 -0
- package/package.json +20 -5
- package/src/api.ts +1 -1
- package/src/app.ts +20 -11
- package/src/bundle-pack.ts +51 -0
- package/src/bundle-runner.ts +463 -0
- package/src/bundle.ts +184 -571
- package/src/diff.ts +208 -174
- package/src/index.ts +15 -17
- package/src/module-manager.ts +15 -15
- package/src/modules/app-module.ts +120 -48
- package/src/modules/bundle-module.ts +21 -11
- package/src/modules/package-module.ts +0 -1
- package/src/modules/user-module.ts +117 -58
- package/src/package.ts +163 -138
- package/src/provider.ts +164 -240
- package/src/types.ts +13 -8
- package/src/utils/app-info-parser/aab.ts +0 -7
- package/src/utils/app-info-parser/apk.ts +9 -6
- package/src/utils/app-info-parser/app.ts +5 -1
- package/src/utils/app-info-parser/index.ts +11 -6
- package/src/utils/app-info-parser/ipa.ts +1 -1
- package/src/utils/app-info-parser/utils.ts +3 -0
- package/src/utils/app-info-parser/xml-parser/manifest.ts +3 -1
- package/src/utils/app-info-parser/zip.ts +12 -14
- package/src/utils/command-result.ts +24 -0
- package/src/utils/index.ts +138 -39
- package/src/utils/latest-version/cli.ts +22 -20
- package/src/utils/latest-version/index.ts +20 -20
- package/src/utils/options.ts +56 -0
- package/src/utils/zip-entries.ts +1 -1
- package/src/workflow-runner.ts +24 -0
- package/index.js +0 -1
|
@@ -15,7 +15,9 @@ export class ManifestParser {
|
|
|
15
15
|
|
|
16
16
|
private collapseAttributes(element: any) {
|
|
17
17
|
const collapsed: Record<string, any> = Object.create(null);
|
|
18
|
-
for (const attr of Array.from(
|
|
18
|
+
for (const attr of Array.from(
|
|
19
|
+
element.attributes as Array<{ name: string; typedValue: { value: any } }>,
|
|
20
|
+
)) {
|
|
19
21
|
collapsed[attr.name] = attr.typedValue.value;
|
|
20
22
|
}
|
|
21
23
|
return collapsed;
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import { decodeNullUnicode } from './utils';
|
|
2
1
|
import path from 'path';
|
|
2
|
+
import { decodeNullUnicode } from './utils';
|
|
3
3
|
|
|
4
4
|
const Unzip = require('isomorphic-unzip');
|
|
5
5
|
|
|
6
6
|
import { enumZipEntries, readEntry } from '../zip-entries';
|
|
7
7
|
|
|
8
8
|
export class Zip {
|
|
9
|
-
file: string;
|
|
9
|
+
file: string | File;
|
|
10
10
|
unzip: any;
|
|
11
11
|
|
|
12
|
-
constructor(file: string) {
|
|
13
|
-
|
|
14
|
-
throw new Error('Param error: [file] must be file path in Node.');
|
|
15
|
-
}
|
|
16
|
-
this.file = path.resolve(file);
|
|
12
|
+
constructor(file: string | File) {
|
|
13
|
+
this.file = typeof file === 'string' ? path.resolve(file) : file;
|
|
17
14
|
this.unzip = new Unzip(this.file);
|
|
18
15
|
}
|
|
19
16
|
|
|
@@ -56,16 +53,17 @@ export class Zip {
|
|
|
56
53
|
});
|
|
57
54
|
}
|
|
58
55
|
|
|
59
|
-
async getEntryFromHarmonyApp(
|
|
56
|
+
async getEntryFromHarmonyApp(
|
|
57
|
+
regex: RegExp,
|
|
58
|
+
): Promise<Buffer | Blob | undefined> {
|
|
60
59
|
try {
|
|
61
60
|
let originSource: Buffer | Blob | undefined;
|
|
62
|
-
|
|
61
|
+
if (typeof this.file !== 'string') {
|
|
62
|
+
throw new Error('Param error: [file] must be file path in Node.');
|
|
63
|
+
}
|
|
64
|
+
await enumZipEntries(this.file, async (entry, zipFile) => {
|
|
63
65
|
if (regex.test(entry.fileName)) {
|
|
64
|
-
|
|
65
|
-
(value: Buffer | Blob | undefined) => {
|
|
66
|
-
originSource = value;
|
|
67
|
-
},
|
|
68
|
-
);
|
|
66
|
+
originSource = await readEntry(entry, zipFile);
|
|
69
67
|
}
|
|
70
68
|
});
|
|
71
69
|
return originSource;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CommandResult } from '../types';
|
|
2
|
+
|
|
3
|
+
export function toErrorMessage(error: unknown, fallback: string): string {
|
|
4
|
+
return error instanceof Error ? error.message : fallback;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function runAsCommandResult<T>(
|
|
8
|
+
task: () => Promise<T>,
|
|
9
|
+
fallbackError: string,
|
|
10
|
+
mapSuccess?: (result: T) => unknown,
|
|
11
|
+
): Promise<CommandResult> {
|
|
12
|
+
try {
|
|
13
|
+
const result = await task();
|
|
14
|
+
return {
|
|
15
|
+
success: true,
|
|
16
|
+
data: mapSuccess ? mapSuccess(result) : result,
|
|
17
|
+
};
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return {
|
|
20
|
+
success: false,
|
|
21
|
+
error: toErrorMessage(error, fallbackError),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -3,6 +3,8 @@ import path from 'path';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { satisfies } from 'compare-versions';
|
|
5
5
|
import fs from 'fs-extra';
|
|
6
|
+
import type { Root as ProtobufRoot } from 'protobufjs';
|
|
7
|
+
import { type Entry as YauzlEntry, open as openZipFile } from 'yauzl';
|
|
6
8
|
import pkg from '../../package.json';
|
|
7
9
|
import latestVersion from '../utils/latest-version';
|
|
8
10
|
import AppInfoParser from './app-info-parser';
|
|
@@ -13,6 +15,77 @@ import { IS_CRESC, tempDir } from './constants';
|
|
|
13
15
|
import { depVersions } from './dep-versions';
|
|
14
16
|
import { t } from './i18n';
|
|
15
17
|
|
|
18
|
+
type ApkMetaEntry = {
|
|
19
|
+
name?: string;
|
|
20
|
+
value?: string | number | Array<string | number>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type ParsedApkInfo = {
|
|
24
|
+
versionName: string;
|
|
25
|
+
application: {
|
|
26
|
+
metaData?: ApkMetaEntry[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type ParsedIpaInfo = {
|
|
31
|
+
CFBundleShortVersionString: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type ParsedAppMetaInfo = {
|
|
35
|
+
versionName?: string;
|
|
36
|
+
pushy_build_time?: number | string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type AabXmlAttr = {
|
|
40
|
+
name: string;
|
|
41
|
+
value: string;
|
|
42
|
+
compiledItem?: {
|
|
43
|
+
ref?: {
|
|
44
|
+
id?: number;
|
|
45
|
+
};
|
|
46
|
+
prim?: {
|
|
47
|
+
intDecimalValue?: number;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type AabXmlElement = {
|
|
53
|
+
name: string;
|
|
54
|
+
attribute: AabXmlAttr[];
|
|
55
|
+
child: Array<{ element?: AabXmlElement }>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
type AabXmlNodeObject = {
|
|
59
|
+
element: AabXmlElement;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
type AabResourceEntry = {
|
|
63
|
+
entryId: number;
|
|
64
|
+
configValue?: Array<{
|
|
65
|
+
value?: {
|
|
66
|
+
item?: {
|
|
67
|
+
str?: {
|
|
68
|
+
value?: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
}>;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
type AabResourceType = {
|
|
76
|
+
typeId: number;
|
|
77
|
+
entry: AabResourceEntry[];
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
type AabResourcePackage = {
|
|
81
|
+
packageId: number;
|
|
82
|
+
type: AabResourceType[];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
type AabResourceTableObject = {
|
|
86
|
+
package: AabResourcePackage[];
|
|
87
|
+
};
|
|
88
|
+
|
|
16
89
|
export async function question(query: string, password?: boolean) {
|
|
17
90
|
if (NO_INTERACTIVE) {
|
|
18
91
|
return '';
|
|
@@ -24,20 +97,29 @@ export async function question(query: string, password?: boolean) {
|
|
|
24
97
|
});
|
|
25
98
|
}
|
|
26
99
|
|
|
27
|
-
export function translateOptions
|
|
28
|
-
|
|
100
|
+
export function translateOptions<T extends Record<string, unknown>>(
|
|
101
|
+
options: T,
|
|
102
|
+
): T & Record<string, unknown> {
|
|
103
|
+
const ret: Record<string, unknown> = {};
|
|
29
104
|
for (const key in options) {
|
|
30
|
-
const
|
|
31
|
-
if (typeof
|
|
32
|
-
ret[key] =
|
|
33
|
-
|
|
34
|
-
(
|
|
35
|
-
|
|
105
|
+
const value = options[key];
|
|
106
|
+
if (typeof value === 'string') {
|
|
107
|
+
ret[key] = value.replace(/\$\{(\w+)\}/g, (placeholder, name) => {
|
|
108
|
+
const replacement = options[name] ?? process.env[name];
|
|
109
|
+
if (
|
|
110
|
+
typeof replacement === 'string' ||
|
|
111
|
+
typeof replacement === 'number' ||
|
|
112
|
+
typeof replacement === 'boolean'
|
|
113
|
+
) {
|
|
114
|
+
return String(replacement);
|
|
115
|
+
}
|
|
116
|
+
return placeholder;
|
|
117
|
+
});
|
|
36
118
|
} else {
|
|
37
|
-
ret[key] =
|
|
119
|
+
ret[key] = value;
|
|
38
120
|
}
|
|
39
121
|
}
|
|
40
|
-
return ret
|
|
122
|
+
return ret as T & Record<string, unknown>;
|
|
41
123
|
}
|
|
42
124
|
|
|
43
125
|
export async function getApkInfo(fn: string) {
|
|
@@ -60,12 +142,18 @@ export async function getApkInfo(fn: string) {
|
|
|
60
142
|
if (updateJsonFile) {
|
|
61
143
|
appCredential = JSON.parse(updateJsonFile.toString()).android;
|
|
62
144
|
}
|
|
63
|
-
const { versionName, application } =
|
|
145
|
+
const { versionName, application } =
|
|
146
|
+
await appInfoParser.parse<ParsedApkInfo>();
|
|
64
147
|
let buildTime = 0;
|
|
65
148
|
if (Array.isArray(application.metaData)) {
|
|
66
149
|
for (const meta of application.metaData) {
|
|
67
150
|
if (meta.name === 'pushy_build_time') {
|
|
68
|
-
|
|
151
|
+
if (Array.isArray(meta.value)) {
|
|
152
|
+
const firstValue = meta.value[0];
|
|
153
|
+
buildTime = Number(firstValue);
|
|
154
|
+
} else if (meta.value !== undefined) {
|
|
155
|
+
buildTime = Number(meta.value);
|
|
156
|
+
}
|
|
69
157
|
}
|
|
70
158
|
}
|
|
71
159
|
}
|
|
@@ -96,14 +184,14 @@ export async function getAppInfo(fn: string) {
|
|
|
96
184
|
}
|
|
97
185
|
const metaJsonFile =
|
|
98
186
|
await appInfoParser.parser.getEntryFromHarmonyApp(/rawfile\/meta.json/);
|
|
99
|
-
let metaData:
|
|
187
|
+
let metaData: ParsedAppMetaInfo = {};
|
|
100
188
|
if (metaJsonFile) {
|
|
101
|
-
metaData = JSON.parse(metaJsonFile.toString());
|
|
189
|
+
metaData = JSON.parse(metaJsonFile.toString()) as ParsedAppMetaInfo;
|
|
102
190
|
}
|
|
103
191
|
const { versionName, pushy_build_time } = metaData;
|
|
104
192
|
let buildTime = 0;
|
|
105
193
|
if (pushy_build_time) {
|
|
106
|
-
buildTime = pushy_build_time;
|
|
194
|
+
buildTime = Number(pushy_build_time);
|
|
107
195
|
}
|
|
108
196
|
if (buildTime == 0) {
|
|
109
197
|
throw new Error(t('buildTimeNotFound'));
|
|
@@ -132,7 +220,7 @@ export async function getIpaInfo(fn: string) {
|
|
|
132
220
|
appCredential = JSON.parse(updateJsonFile.toString()).ios;
|
|
133
221
|
}
|
|
134
222
|
const { CFBundleShortVersionString: versionName } =
|
|
135
|
-
await appInfoParser.parse();
|
|
223
|
+
await appInfoParser.parse<ParsedIpaInfo>();
|
|
136
224
|
let buildTimeTxtBuffer = await appInfoParser.parser.getEntry(
|
|
137
225
|
/payload\/.+?\.app\/pushy_build_time.txt/,
|
|
138
226
|
);
|
|
@@ -150,7 +238,7 @@ export async function getIpaInfo(fn: string) {
|
|
|
150
238
|
}
|
|
151
239
|
|
|
152
240
|
export async function getAabInfo(fn: string) {
|
|
153
|
-
const protobuf = require('protobufjs');
|
|
241
|
+
const protobuf = require('protobufjs') as typeof import('protobufjs');
|
|
154
242
|
const root = await protobuf.load(
|
|
155
243
|
path.join(__dirname, '../../proto/Resources.proto'),
|
|
156
244
|
);
|
|
@@ -165,7 +253,7 @@ export async function getAabInfo(fn: string) {
|
|
|
165
253
|
bytes: String,
|
|
166
254
|
defaults: true,
|
|
167
255
|
arrays: true,
|
|
168
|
-
});
|
|
256
|
+
}) as AabXmlNodeObject;
|
|
169
257
|
|
|
170
258
|
const manifestElement = object.element;
|
|
171
259
|
if (manifestElement.name !== 'manifest') {
|
|
@@ -184,18 +272,23 @@ export async function getAabInfo(fn: string) {
|
|
|
184
272
|
|
|
185
273
|
// Find application node
|
|
186
274
|
const applicationNode = manifestElement.child.find(
|
|
187
|
-
(
|
|
275
|
+
(child) => child.element?.name === 'application',
|
|
188
276
|
);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
277
|
+
const applicationElement = applicationNode?.element;
|
|
278
|
+
if (applicationElement) {
|
|
279
|
+
const metaDataNodes = applicationElement.child.filter(
|
|
280
|
+
(child) => child.element?.name === 'meta-data',
|
|
192
281
|
);
|
|
193
282
|
for (const meta of metaDataNodes) {
|
|
194
283
|
let name = '';
|
|
195
284
|
let value = '';
|
|
196
285
|
let resourceId = 0;
|
|
197
286
|
|
|
198
|
-
|
|
287
|
+
const metaElement = meta.element;
|
|
288
|
+
if (!metaElement) {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
for (const attr of metaElement.attribute) {
|
|
199
292
|
if (attr.name === 'name') {
|
|
200
293
|
name = attr.value;
|
|
201
294
|
}
|
|
@@ -229,19 +322,24 @@ export async function getAabInfo(fn: string) {
|
|
|
229
322
|
}
|
|
230
323
|
|
|
231
324
|
async function readZipEntry(fn: string, entryName: string): Promise<Buffer> {
|
|
232
|
-
const yauzl = require('yauzl');
|
|
233
325
|
return new Promise((resolve, reject) => {
|
|
234
|
-
|
|
235
|
-
if (err
|
|
326
|
+
openZipFile(fn, { lazyEntries: true }, (err, zipfile) => {
|
|
327
|
+
if (err || !zipfile) {
|
|
328
|
+
reject(err ?? new Error('Failed to open zip file'));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
236
331
|
let found = false;
|
|
237
332
|
zipfile.readEntry();
|
|
238
|
-
zipfile.on('entry', (entry:
|
|
333
|
+
zipfile.on('entry', (entry: YauzlEntry) => {
|
|
239
334
|
if (entry.fileName === entryName) {
|
|
240
335
|
found = true;
|
|
241
|
-
zipfile.openReadStream(entry, (
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
336
|
+
zipfile.openReadStream(entry, (streamError, readStream) => {
|
|
337
|
+
if (streamError || !readStream) {
|
|
338
|
+
reject(streamError ?? new Error('Failed to read zip entry'));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const chunks: Buffer[] = [];
|
|
342
|
+
readStream.on('data', (chunk: Buffer) => chunks.push(chunk));
|
|
245
343
|
readStream.on('end', () => resolve(Buffer.concat(chunks)));
|
|
246
344
|
readStream.on('error', reject);
|
|
247
345
|
});
|
|
@@ -260,7 +358,7 @@ async function readZipEntry(fn: string, entryName: string): Promise<Buffer> {
|
|
|
260
358
|
async function resolveResource(
|
|
261
359
|
fn: string,
|
|
262
360
|
resourceId: number,
|
|
263
|
-
root:
|
|
361
|
+
root: ProtobufRoot,
|
|
264
362
|
): Promise<string | null> {
|
|
265
363
|
const pkgId = (resourceId >> 24) & 0xff;
|
|
266
364
|
const typeId = (resourceId >> 16) & 0xff;
|
|
@@ -276,25 +374,26 @@ async function resolveResource(
|
|
|
276
374
|
bytes: String,
|
|
277
375
|
defaults: true,
|
|
278
376
|
arrays: true,
|
|
279
|
-
});
|
|
377
|
+
}) as AabResourceTableObject;
|
|
280
378
|
|
|
281
379
|
// Find package
|
|
282
|
-
const pkg = object.package.find((
|
|
380
|
+
const pkg = object.package.find((pkgItem) => pkgItem.packageId === pkgId);
|
|
283
381
|
if (!pkg) return null;
|
|
284
382
|
|
|
285
383
|
// Find type
|
|
286
|
-
const type = pkg.type.find((
|
|
384
|
+
const type = pkg.type.find((typeItem) => typeItem.typeId === typeId);
|
|
287
385
|
if (!type) return null;
|
|
288
386
|
|
|
289
387
|
// Find entry
|
|
290
|
-
const entry = type.entry.find((
|
|
388
|
+
const entry = type.entry.find((entryItem) => entryItem.entryId === entryId);
|
|
291
389
|
if (!entry) return null;
|
|
292
390
|
|
|
293
391
|
// Get value from configValue
|
|
294
392
|
if (entry.configValue && entry.configValue.length > 0) {
|
|
295
|
-
const val = entry.configValue[0]
|
|
296
|
-
|
|
297
|
-
|
|
393
|
+
const val = entry.configValue[0]?.value;
|
|
394
|
+
const stringValue = val?.item?.str?.value;
|
|
395
|
+
if (typeof stringValue === 'string') {
|
|
396
|
+
return stringValue;
|
|
298
397
|
}
|
|
299
398
|
}
|
|
300
399
|
} catch (e) {
|
|
@@ -122,13 +122,13 @@ const drawBox = (
|
|
|
122
122
|
);
|
|
123
123
|
|
|
124
124
|
console.log(color(`┌${'─'.repeat(maxLineWidth + horizontalPadding * 2)}┐`));
|
|
125
|
-
|
|
125
|
+
for (const row of lines) {
|
|
126
126
|
const padding = ' '.repeat(horizontalPadding);
|
|
127
127
|
const fullRow = `${row}${' '.repeat(maxLineWidth - strip(row).length)}`;
|
|
128
128
|
console.log(
|
|
129
129
|
`${color('│')}${padding}${reset(fullRow)}${padding}${color('│')}`,
|
|
130
130
|
);
|
|
131
|
-
}
|
|
131
|
+
}
|
|
132
132
|
console.log(color(`└${'─'.repeat(maxLineWidth + horizontalPadding * 2)}┘`));
|
|
133
133
|
};
|
|
134
134
|
|
|
@@ -191,15 +191,15 @@ const getTableColumns = (rows: TableRow[]): TableColumn[] => {
|
|
|
191
191
|
items: [],
|
|
192
192
|
},
|
|
193
193
|
];
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
for (const row of rows) {
|
|
195
|
+
for (const column of columns) {
|
|
196
196
|
column.maxLength = Math.max(
|
|
197
197
|
column.label.length,
|
|
198
198
|
column.maxLength,
|
|
199
199
|
row[column.attrName].length || 0,
|
|
200
200
|
);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
203
|
return columns;
|
|
204
204
|
};
|
|
205
205
|
|
|
@@ -217,13 +217,16 @@ const getTableRows = (updates: LatestVersionPackage[]): TableRow[] => {
|
|
|
217
217
|
const getGroup = (a?: string, b?: string): TableRowGroup => {
|
|
218
218
|
if (b && semverMajor(b) === 0) {
|
|
219
219
|
return 'majorVersionZero';
|
|
220
|
-
}
|
|
220
|
+
}
|
|
221
|
+
if (a && b) {
|
|
221
222
|
const releaseType = semverDiff(a, b) ?? '';
|
|
222
223
|
if (['major', 'premajor', 'prerelease'].includes(releaseType)) {
|
|
223
224
|
return 'major';
|
|
224
|
-
}
|
|
225
|
+
}
|
|
226
|
+
if (['minor', 'preminor'].includes(releaseType)) {
|
|
225
227
|
return 'minor';
|
|
226
|
-
}
|
|
228
|
+
}
|
|
229
|
+
if (['patch', 'prepatch'].includes(releaseType)) {
|
|
227
230
|
return 'patch';
|
|
228
231
|
}
|
|
229
232
|
}
|
|
@@ -236,7 +239,7 @@ const getTableRows = (updates: LatestVersionPackage[]): TableRow[] => {
|
|
|
236
239
|
wanted?: string,
|
|
237
240
|
) =>
|
|
238
241
|
all.push({
|
|
239
|
-
name:
|
|
242
|
+
name: ` ${name}`,
|
|
240
243
|
location,
|
|
241
244
|
installed: installed ?? 'unknown',
|
|
242
245
|
latest: latest ?? 'unknown',
|
|
@@ -368,21 +371,20 @@ const checkVersions = async (
|
|
|
368
371
|
skipMissing: boolean,
|
|
369
372
|
options: LatestVersionOptions = { useCache: true },
|
|
370
373
|
): Promise<void> => {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
options
|
|
379
|
-
|
|
374
|
+
console.log(cyan('Checking versions...'));
|
|
375
|
+
let latestVersionPackages: LatestVersionPackage[];
|
|
376
|
+
if (typeof packages === 'string') {
|
|
377
|
+
latestVersionPackages = [await latestVersion(packages, options)];
|
|
378
|
+
} else if (Array.isArray(packages)) {
|
|
379
|
+
latestVersionPackages = await latestVersion(packages, options);
|
|
380
|
+
} else {
|
|
381
|
+
latestVersionPackages = await latestVersion(packages, options);
|
|
382
|
+
}
|
|
380
383
|
if (skipMissing) {
|
|
381
384
|
latestVersionPackages = latestVersionPackages.filter(
|
|
382
385
|
(pkg) => pkg.local ?? pkg.globalNpm ?? pkg.globalYarn,
|
|
383
386
|
);
|
|
384
387
|
}
|
|
385
|
-
spinner.stop();
|
|
386
388
|
displayTable(latestVersionPackages);
|
|
387
389
|
};
|
|
388
390
|
|
|
@@ -363,7 +363,8 @@ const getInstalledVersion = (
|
|
|
363
363
|
if (location === 'globalNpm') {
|
|
364
364
|
return require(join(npm.packages, pkgName, 'package.json'))
|
|
365
365
|
?.version as string;
|
|
366
|
-
}
|
|
366
|
+
}
|
|
367
|
+
if (location === 'globalYarn') {
|
|
367
368
|
// Make sure package is globally installed by Yarn
|
|
368
369
|
const yarnGlobalPkg = require(
|
|
369
370
|
pathResolve(yarn.packages, '..', 'package.json'),
|
|
@@ -373,25 +374,24 @@ const getInstalledVersion = (
|
|
|
373
374
|
}
|
|
374
375
|
return require(join(yarn.packages, pkgName, 'package.json'))
|
|
375
376
|
?.version as string;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Compute the local paths manually as require.resolve() and require.resolve.paths()
|
|
380
|
+
* cannot be trusted anymore.
|
|
381
|
+
* @see https://github.com/nodejs/node/issues/33460
|
|
382
|
+
* @see https://github.com/nodejs/loaders/issues/26
|
|
383
|
+
*/
|
|
384
|
+
const { root } = parse(process.cwd());
|
|
385
|
+
let path = process.cwd();
|
|
386
|
+
const localPaths = [join(path, 'node_modules')];
|
|
387
|
+
while (path !== root) {
|
|
388
|
+
path = dirname(path);
|
|
389
|
+
localPaths.push(join(path, 'node_modules'));
|
|
390
|
+
}
|
|
391
|
+
for (const localPath of localPaths) {
|
|
392
|
+
const pkgPath = join(localPath, pkgName, 'package.json');
|
|
393
|
+
if (existsSync(pkgPath)) {
|
|
394
|
+
return require(pkgPath)?.version as string;
|
|
395
395
|
}
|
|
396
396
|
}
|
|
397
397
|
return undefined;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export function getBooleanOption(
|
|
2
|
+
options: Record<string, unknown>,
|
|
3
|
+
key: string,
|
|
4
|
+
fallback = false,
|
|
5
|
+
): boolean {
|
|
6
|
+
const value = options[key];
|
|
7
|
+
if (typeof value === 'boolean') {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
if (typeof value === 'string') {
|
|
11
|
+
return value.toLowerCase() === 'true';
|
|
12
|
+
}
|
|
13
|
+
if (typeof value === 'number') {
|
|
14
|
+
return value !== 0;
|
|
15
|
+
}
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getStringOption(
|
|
20
|
+
options: Record<string, unknown>,
|
|
21
|
+
key: string,
|
|
22
|
+
fallback = '',
|
|
23
|
+
): string {
|
|
24
|
+
const value = options[key];
|
|
25
|
+
if (typeof value === 'string') {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
29
|
+
return String(value);
|
|
30
|
+
}
|
|
31
|
+
return fallback;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getOptionalStringOption(
|
|
35
|
+
options: Record<string, unknown>,
|
|
36
|
+
key: string,
|
|
37
|
+
): string | undefined {
|
|
38
|
+
const value = options[key];
|
|
39
|
+
if (typeof value === 'string') {
|
|
40
|
+
return value || undefined;
|
|
41
|
+
}
|
|
42
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
43
|
+
return String(value);
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function toObjectState<T extends Record<string, unknown>>(
|
|
49
|
+
value: unknown,
|
|
50
|
+
fallback: T,
|
|
51
|
+
): T {
|
|
52
|
+
if (value && typeof value === 'object') {
|
|
53
|
+
return value as T;
|
|
54
|
+
}
|
|
55
|
+
return fallback;
|
|
56
|
+
}
|
package/src/utils/zip-entries.ts
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CommandContext, CustomWorkflow } from './types';
|
|
2
|
+
|
|
3
|
+
export async function runWorkflow(
|
|
4
|
+
workflowName: string,
|
|
5
|
+
workflow: CustomWorkflow,
|
|
6
|
+
context: CommandContext,
|
|
7
|
+
): Promise<unknown> {
|
|
8
|
+
if (workflow.validate && !workflow.validate(context)) {
|
|
9
|
+
throw new Error(`Workflow '${workflowName}' validation failed`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let previousResult: unknown;
|
|
13
|
+
for (const step of workflow.steps) {
|
|
14
|
+
if (step.condition && !step.condition(context)) {
|
|
15
|
+
console.log(`Skipping step '${step.name}' due to condition`);
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
console.log(`Executing step '${step.name}'`);
|
|
20
|
+
previousResult = await step.execute(context, previousResult);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return previousResult;
|
|
24
|
+
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('./lib');
|