react-native-update-cli 2.4.2 → 2.6.0
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/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/cli.json +40 -0
- package/lib/api.js +1 -1
- package/lib/locales/en.js +16 -1
- package/lib/locales/zh.js +16 -1
- package/lib/package.js +60 -6
- package/lib/provider.js +3 -0
- package/lib/utils/app-info-parser/aab.js +230 -0
- package/lib/utils/app-info-parser/apk.js +25 -27
- package/lib/utils/app-info-parser/app.js +10 -11
- package/lib/utils/app-info-parser/index.js +13 -8
- package/lib/utils/app-info-parser/ipa.js +16 -21
- package/lib/utils/app-info-parser/resource-finder.js +365 -305
- package/lib/utils/app-info-parser/utils.js +78 -63
- package/lib/utils/app-info-parser/xml-parser/binary.js +57 -51
- package/lib/utils/app-info-parser/xml-parser/manifest.js +47 -39
- package/lib/utils/app-info-parser/zip.js +21 -11
- package/lib/utils/http-helper.js +1 -1
- package/lib/utils/index.js +137 -0
- package/lib/versions.js +22 -0
- package/package.json +3 -2
- package/proto/Configuration.proto +183 -0
- package/proto/Resources.proto +569 -0
- package/src/api.ts +2 -6
- package/src/locales/en.ts +20 -0
- package/src/locales/zh.ts +18 -0
- package/src/modules/version-module.ts +1 -1
- package/src/package.ts +112 -12
- package/src/provider.ts +3 -0
- package/src/utils/app-info-parser/aab.ts +240 -0
- package/src/utils/app-info-parser/{apk.js → apk.ts} +30 -41
- package/src/utils/app-info-parser/app.ts +3 -0
- package/src/utils/app-info-parser/index.ts +9 -5
- package/src/utils/app-info-parser/{ipa.js → ipa.ts} +17 -31
- package/src/utils/app-info-parser/resource-finder.ts +508 -0
- package/src/utils/app-info-parser/utils.ts +162 -0
- package/src/utils/app-info-parser/xml-parser/{binary.js → binary.ts} +69 -61
- package/src/utils/app-info-parser/xml-parser/{manifest.js → manifest.ts} +50 -51
- package/src/utils/app-info-parser/zip.ts +86 -0
- package/src/utils/dep-versions.ts +7 -4
- package/src/utils/http-helper.ts +1 -1
- package/src/utils/index.ts +154 -0
- package/src/utils/latest-version/index.ts +2 -1
- package/src/versions.ts +27 -2
- package/src/utils/app-info-parser/app.js +0 -16
- package/src/utils/app-info-parser/resource-finder.js +0 -495
- package/src/utils/app-info-parser/utils.js +0 -172
- package/src/utils/app-info-parser/zip.js +0 -66
package/src/utils/http-helper.ts
CHANGED
package/src/utils/index.ts
CHANGED
|
@@ -149,6 +149,160 @@ export async function getIpaInfo(fn: string) {
|
|
|
149
149
|
return { versionName, buildTime, ...appCredential };
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
export async function getAabInfo(fn: string) {
|
|
153
|
+
const protobuf = require('protobufjs');
|
|
154
|
+
const root = await protobuf.load(
|
|
155
|
+
path.join(__dirname, '../../proto/Resources.proto'),
|
|
156
|
+
);
|
|
157
|
+
const XmlNode = root.lookupType('aapt.pb.XmlNode');
|
|
158
|
+
|
|
159
|
+
const buffer = await readZipEntry(fn, 'base/manifest/AndroidManifest.xml');
|
|
160
|
+
|
|
161
|
+
const message = XmlNode.decode(buffer);
|
|
162
|
+
const object = XmlNode.toObject(message, {
|
|
163
|
+
enums: String,
|
|
164
|
+
longs: String,
|
|
165
|
+
bytes: String,
|
|
166
|
+
defaults: true,
|
|
167
|
+
arrays: true,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const manifestElement = object.element;
|
|
171
|
+
if (manifestElement.name !== 'manifest') {
|
|
172
|
+
throw new Error('Invalid manifest');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let versionName = '';
|
|
176
|
+
for (const attr of manifestElement.attribute) {
|
|
177
|
+
if (attr.name === 'versionName') {
|
|
178
|
+
versionName = attr.value;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let buildTime = 0;
|
|
183
|
+
const appCredential = {};
|
|
184
|
+
|
|
185
|
+
// Find application node
|
|
186
|
+
const applicationNode = manifestElement.child.find(
|
|
187
|
+
(c: any) => c.element && c.element.name === 'application',
|
|
188
|
+
);
|
|
189
|
+
if (applicationNode) {
|
|
190
|
+
const metaDataNodes = applicationNode.element.child.filter(
|
|
191
|
+
(c: any) => c.element && c.element.name === 'meta-data',
|
|
192
|
+
);
|
|
193
|
+
for (const meta of metaDataNodes) {
|
|
194
|
+
let name = '';
|
|
195
|
+
let value = '';
|
|
196
|
+
let resourceId = 0;
|
|
197
|
+
|
|
198
|
+
for (const attr of meta.element.attribute) {
|
|
199
|
+
if (attr.name === 'name') {
|
|
200
|
+
name = attr.value;
|
|
201
|
+
}
|
|
202
|
+
if (attr.name === 'value') {
|
|
203
|
+
value = attr.value;
|
|
204
|
+
if (attr.compiledItem?.ref?.id) {
|
|
205
|
+
resourceId = attr.compiledItem.ref.id;
|
|
206
|
+
} else if (attr.compiledItem?.prim?.intDecimalValue) {
|
|
207
|
+
value = attr.compiledItem.prim.intDecimalValue.toString();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (name === 'pushy_build_time') {
|
|
213
|
+
if (resourceId > 0) {
|
|
214
|
+
const resolvedValue = await resolveResource(fn, resourceId, root);
|
|
215
|
+
if (resolvedValue) {
|
|
216
|
+
value = resolvedValue;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
buildTime = Number(value);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (buildTime === 0) {
|
|
225
|
+
throw new Error(t('buildTimeNotFound'));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return { versionName, buildTime, ...appCredential };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function readZipEntry(fn: string, entryName: string): Promise<Buffer> {
|
|
232
|
+
const yauzl = require('yauzl');
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
yauzl.open(fn, { lazyEntries: true }, (err: any, zipfile: any) => {
|
|
235
|
+
if (err) return reject(err);
|
|
236
|
+
let found = false;
|
|
237
|
+
zipfile.readEntry();
|
|
238
|
+
zipfile.on('entry', (entry: any) => {
|
|
239
|
+
if (entry.fileName === entryName) {
|
|
240
|
+
found = true;
|
|
241
|
+
zipfile.openReadStream(entry, (err: any, readStream: any) => {
|
|
242
|
+
if (err) return reject(err);
|
|
243
|
+
const chunks: any[] = [];
|
|
244
|
+
readStream.on('data', (chunk: any) => chunks.push(chunk));
|
|
245
|
+
readStream.on('end', () => resolve(Buffer.concat(chunks)));
|
|
246
|
+
readStream.on('error', reject);
|
|
247
|
+
});
|
|
248
|
+
} else {
|
|
249
|
+
zipfile.readEntry();
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
zipfile.on('end', () => {
|
|
253
|
+
if (!found) reject(new Error(`${entryName} not found in AAB`));
|
|
254
|
+
});
|
|
255
|
+
zipfile.on('error', reject);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function resolveResource(
|
|
261
|
+
fn: string,
|
|
262
|
+
resourceId: number,
|
|
263
|
+
root: any,
|
|
264
|
+
): Promise<string | null> {
|
|
265
|
+
const pkgId = (resourceId >> 24) & 0xff;
|
|
266
|
+
const typeId = (resourceId >> 16) & 0xff;
|
|
267
|
+
const entryId = resourceId & 0xffff;
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const buffer = await readZipEntry(fn, 'base/resources.pb');
|
|
271
|
+
const ResourceTable = root.lookupType('aapt.pb.ResourceTable');
|
|
272
|
+
const message = ResourceTable.decode(buffer);
|
|
273
|
+
const object = ResourceTable.toObject(message, {
|
|
274
|
+
enums: String,
|
|
275
|
+
longs: String,
|
|
276
|
+
bytes: String,
|
|
277
|
+
defaults: true,
|
|
278
|
+
arrays: true,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Find package
|
|
282
|
+
const pkg = object.package.find((p: any) => p.packageId === pkgId);
|
|
283
|
+
if (!pkg) return null;
|
|
284
|
+
|
|
285
|
+
// Find type
|
|
286
|
+
const type = pkg.type.find((t: any) => t.typeId === typeId);
|
|
287
|
+
if (!type) return null;
|
|
288
|
+
|
|
289
|
+
// Find entry
|
|
290
|
+
const entry = type.entry.find((e: any) => e.entryId === entryId);
|
|
291
|
+
if (!entry) return null;
|
|
292
|
+
|
|
293
|
+
// Get value from configValue
|
|
294
|
+
if (entry.configValue && entry.configValue.length > 0) {
|
|
295
|
+
const val = entry.configValue[0].value;
|
|
296
|
+
if (val.item?.str) {
|
|
297
|
+
return val.item.str.value;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
} catch (e) {
|
|
301
|
+
console.warn('Failed to resolve resource:', e);
|
|
302
|
+
}
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
|
|
152
306
|
const localDir = path.resolve(os.homedir(), tempDir);
|
|
153
307
|
fs.ensureDirSync(localDir);
|
|
154
308
|
export function saveToLocal(originPath: string, destName: string) {
|
|
@@ -227,7 +227,8 @@ const downloadMetadata = (
|
|
|
227
227
|
};
|
|
228
228
|
const authInfo = registryAuthToken(pkgUrl.toString(), { recursive: true });
|
|
229
229
|
if (authInfo && requestOptions.headers) {
|
|
230
|
-
(requestOptions.headers as any).authorization =
|
|
230
|
+
(requestOptions.headers as any).authorization =
|
|
231
|
+
`${authInfo.type} ${authInfo.token}`;
|
|
231
232
|
}
|
|
232
233
|
if (options?.requestOptions) {
|
|
233
234
|
requestOptions = { ...requestOptions, ...options.requestOptions };
|
package/src/versions.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { get, getAllPackages, post, put, uploadFile } from './api';
|
|
1
|
+
import { get, getAllPackages, post, put, uploadFile, doDelete } from './api';
|
|
2
2
|
import { question, saveToLocal } from './utils';
|
|
3
3
|
import { t } from './utils/i18n';
|
|
4
4
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { satisfies } from 'compare-versions';
|
|
7
|
-
import type { Package, Platform, Version } from './types';
|
|
8
7
|
import { getPlatform, getSelectedApp } from './app';
|
|
9
8
|
import { choosePackage } from './package';
|
|
9
|
+
import type { Package, Platform, Version } from './types';
|
|
10
10
|
import { depVersions } from './utils/dep-versions';
|
|
11
11
|
import { getCommitInfo } from './utils/git';
|
|
12
12
|
|
|
@@ -343,4 +343,29 @@ export const versionCommands = {
|
|
|
343
343
|
await put(`/app/${appId}/version/${versionId}`, updateParams);
|
|
344
344
|
console.log(t('operationSuccess'));
|
|
345
345
|
},
|
|
346
|
+
deleteVersion: async ({
|
|
347
|
+
options,
|
|
348
|
+
}: {
|
|
349
|
+
options: VersionCommandOptions;
|
|
350
|
+
}) => {
|
|
351
|
+
let appId = options.appId;
|
|
352
|
+
if (!appId) {
|
|
353
|
+
const platform = await getPlatform(options.platform);
|
|
354
|
+
appId = (await getSelectedApp(platform)).appId;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
let versionId = options.versionId;
|
|
358
|
+
if (!versionId) {
|
|
359
|
+
versionId = (await chooseVersion(appId as string)).id;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
await doDelete(`/app/${appId}/version/${versionId}`);
|
|
364
|
+
console.log(t('deleteVersionSuccess', { versionId }));
|
|
365
|
+
} catch (error: any) {
|
|
366
|
+
throw new Error(
|
|
367
|
+
t('deleteVersionError', { versionId, error: error.message }),
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
},
|
|
346
371
|
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const Zip = require('./zip');
|
|
2
|
-
|
|
3
|
-
class AppParser extends Zip {
|
|
4
|
-
/**
|
|
5
|
-
* parser for parsing .apk file
|
|
6
|
-
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
|
|
7
|
-
*/
|
|
8
|
-
constructor(file) {
|
|
9
|
-
super(file);
|
|
10
|
-
if (!(this instanceof AppParser)) {
|
|
11
|
-
return new AppParser(file);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = AppParser;
|