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.
Files changed (49) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +2 -0
  3. package/cli.json +40 -0
  4. package/lib/api.js +1 -1
  5. package/lib/locales/en.js +16 -1
  6. package/lib/locales/zh.js +16 -1
  7. package/lib/package.js +60 -6
  8. package/lib/provider.js +3 -0
  9. package/lib/utils/app-info-parser/aab.js +230 -0
  10. package/lib/utils/app-info-parser/apk.js +25 -27
  11. package/lib/utils/app-info-parser/app.js +10 -11
  12. package/lib/utils/app-info-parser/index.js +13 -8
  13. package/lib/utils/app-info-parser/ipa.js +16 -21
  14. package/lib/utils/app-info-parser/resource-finder.js +365 -305
  15. package/lib/utils/app-info-parser/utils.js +78 -63
  16. package/lib/utils/app-info-parser/xml-parser/binary.js +57 -51
  17. package/lib/utils/app-info-parser/xml-parser/manifest.js +47 -39
  18. package/lib/utils/app-info-parser/zip.js +21 -11
  19. package/lib/utils/http-helper.js +1 -1
  20. package/lib/utils/index.js +137 -0
  21. package/lib/versions.js +22 -0
  22. package/package.json +3 -2
  23. package/proto/Configuration.proto +183 -0
  24. package/proto/Resources.proto +569 -0
  25. package/src/api.ts +2 -6
  26. package/src/locales/en.ts +20 -0
  27. package/src/locales/zh.ts +18 -0
  28. package/src/modules/version-module.ts +1 -1
  29. package/src/package.ts +112 -12
  30. package/src/provider.ts +3 -0
  31. package/src/utils/app-info-parser/aab.ts +240 -0
  32. package/src/utils/app-info-parser/{apk.js → apk.ts} +30 -41
  33. package/src/utils/app-info-parser/app.ts +3 -0
  34. package/src/utils/app-info-parser/index.ts +9 -5
  35. package/src/utils/app-info-parser/{ipa.js → ipa.ts} +17 -31
  36. package/src/utils/app-info-parser/resource-finder.ts +508 -0
  37. package/src/utils/app-info-parser/utils.ts +162 -0
  38. package/src/utils/app-info-parser/xml-parser/{binary.js → binary.ts} +69 -61
  39. package/src/utils/app-info-parser/xml-parser/{manifest.js → manifest.ts} +50 -51
  40. package/src/utils/app-info-parser/zip.ts +86 -0
  41. package/src/utils/dep-versions.ts +7 -4
  42. package/src/utils/http-helper.ts +1 -1
  43. package/src/utils/index.ts +154 -0
  44. package/src/utils/latest-version/index.ts +2 -1
  45. package/src/versions.ts +27 -2
  46. package/src/utils/app-info-parser/app.js +0 -16
  47. package/src/utils/app-info-parser/resource-finder.js +0 -495
  48. package/src/utils/app-info-parser/utils.js +0 -172
  49. package/src/utils/app-info-parser/zip.js +0 -66
@@ -1,5 +1,5 @@
1
- import { defaultEndpoints } from './constants';
2
1
  import fetch from 'node-fetch';
2
+ import { defaultEndpoints } from './constants';
3
3
 
4
4
  // const baseUrl = `http://localhost:9000`;
5
5
  // let baseUrl = SERVER.main[0];
@@ -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 = `${authInfo.type} ${authInfo.token}`;
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;