react-native-update 10.28.1 → 10.28.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-update",
3
- "version": "10.28.1",
3
+ "version": "10.28.2",
4
4
  "description": "react-native hot update",
5
5
  "main": "src/index",
6
6
  "scripts": {
@@ -74,6 +74,5 @@
74
74
  "react-native": "0.73",
75
75
  "ts-jest": "^29.2.5",
76
76
  "typescript": "^5.6.3"
77
- },
78
- "packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
77
+ }
79
78
  }
package/src/client.ts CHANGED
@@ -61,6 +61,31 @@ const defaultClientOptions: ClientOptions = {
61
61
  throwError: false,
62
62
  };
63
63
 
64
+ export const sharedState: {
65
+ progressHandlers: Record<string, EmitterSubscription>;
66
+ downloadedHash?: string;
67
+ apkStatus: 'downloading' | 'downloaded' | null;
68
+ marked: boolean;
69
+ applyingUpdate: boolean;
70
+ } = {
71
+ progressHandlers: {},
72
+ downloadedHash: undefined,
73
+ apkStatus: null,
74
+ marked: false,
75
+ applyingUpdate: false,
76
+ };
77
+
78
+ const assertHash = (hash: string) => {
79
+ if (!sharedState.downloadedHash) {
80
+ return;
81
+ }
82
+ if (hash !== sharedState.downloadedHash) {
83
+ log(`use downloaded hash ${sharedState.downloadedHash} first`);
84
+ return;
85
+ }
86
+ return true;
87
+ };
88
+
64
89
  // for China users
65
90
  export class Pushy {
66
91
  options = defaultClientOptions;
@@ -68,13 +93,6 @@ export class Pushy {
68
93
  lastChecking?: number;
69
94
  lastRespJson?: Promise<any>;
70
95
 
71
- static progressHandlers: Record<string, EmitterSubscription> = {};
72
- static downloadedHash?: string;
73
-
74
- static apkStatus: 'downloading' | 'downloaded' | null = null;
75
-
76
- static marked = false;
77
- static applyingUpdate = false;
78
96
  version = cInfo.rnu;
79
97
  loggerPromise = (() => {
80
98
  let resolve: (value?: unknown) => void = () => {};
@@ -152,16 +170,6 @@ export class Pushy {
152
170
  getCheckUrl = (endpoint: string = this.options.server!.main) => {
153
171
  return `${endpoint}/checkUpdate/${this.options.appKey}`;
154
172
  };
155
- static assertHash = (hash: string) => {
156
- if (!this.downloadedHash) {
157
- return;
158
- }
159
- if (hash !== this.downloadedHash) {
160
- log(`use downloaded hash ${Pushy.downloadedHash} first`);
161
- return;
162
- }
163
- return true;
164
- };
165
173
  assertDebug = () => {
166
174
  if (__DEV__ && !this.options.debug) {
167
175
  console.info(
@@ -172,10 +180,10 @@ export class Pushy {
172
180
  return true;
173
181
  };
174
182
  markSuccess = () => {
175
- if (Pushy.marked || __DEV__ || !isFirstTime) {
183
+ if (sharedState.marked || __DEV__ || !isFirstTime) {
176
184
  return;
177
185
  }
178
- Pushy.marked = true;
186
+ sharedState.marked = true;
179
187
  PushyModule.markSuccess();
180
188
  this.report({ type: 'markSuccess' });
181
189
  };
@@ -183,9 +191,9 @@ export class Pushy {
183
191
  if (!assertDev('switchVersion()')) {
184
192
  return;
185
193
  }
186
- if (Pushy.assertHash(hash) && !Pushy.applyingUpdate) {
194
+ if (assertHash(hash) && !sharedState.applyingUpdate) {
187
195
  log('switchVersion: ' + hash);
188
- Pushy.applyingUpdate = true;
196
+ sharedState.applyingUpdate = true;
189
197
  return PushyModule.reloadUpdate({ hash });
190
198
  }
191
199
  };
@@ -194,7 +202,7 @@ export class Pushy {
194
202
  if (!assertDev('switchVersionLater()')) {
195
203
  return;
196
204
  }
197
- if (Pushy.assertHash(hash)) {
205
+ if (assertHash(hash)) {
198
206
  log('switchVersionLater: ' + hash);
199
207
  return PushyModule.setNeedUpdate({ hash });
200
208
  }
@@ -349,18 +357,18 @@ export class Pushy {
349
357
  log(`rolledback hash ${rolledBackVersion}, ignored`);
350
358
  return;
351
359
  }
352
- if (Pushy.downloadedHash === hash) {
353
- log(`duplicated downloaded hash ${Pushy.downloadedHash}, ignored`);
354
- return Pushy.downloadedHash;
360
+ if (sharedState.downloadedHash === hash) {
361
+ log(`duplicated downloaded hash ${sharedState.downloadedHash}, ignored`);
362
+ return sharedState.downloadedHash;
355
363
  }
356
- if (Pushy.progressHandlers[hash]) {
364
+ if (sharedState.progressHandlers[hash]) {
357
365
  return;
358
366
  }
359
367
  const patchStartTime = Date.now();
360
368
  if (onDownloadProgress) {
361
369
  // @ts-expect-error harmony not in existing platforms
362
370
  if (Platform.OS === 'harmony') {
363
- Pushy.progressHandlers[hash] = DeviceEventEmitter.addListener(
371
+ sharedState.progressHandlers[hash] = DeviceEventEmitter.addListener(
364
372
  'RCTPushyDownloadProgress',
365
373
  progressData => {
366
374
  if (progressData.hash === hash) {
@@ -369,14 +377,15 @@ export class Pushy {
369
377
  },
370
378
  );
371
379
  } else {
372
- Pushy.progressHandlers[hash] = pushyNativeEventEmitter.addListener(
373
- 'RCTPushyDownloadProgress',
374
- progressData => {
375
- if (progressData.hash === hash) {
376
- onDownloadProgress(progressData);
377
- }
378
- },
379
- );
380
+ sharedState.progressHandlers[hash] =
381
+ pushyNativeEventEmitter.addListener(
382
+ 'RCTPushyDownloadProgress',
383
+ progressData => {
384
+ if (progressData.hash === hash) {
385
+ onDownloadProgress(progressData);
386
+ }
387
+ },
388
+ );
380
389
  }
381
390
  }
382
391
  let succeeded = '';
@@ -444,9 +453,9 @@ export class Pushy {
444
453
  }
445
454
  }
446
455
  }
447
- if (Pushy.progressHandlers[hash]) {
448
- Pushy.progressHandlers[hash].remove();
449
- delete Pushy.progressHandlers[hash];
456
+ if (sharedState.progressHandlers[hash]) {
457
+ sharedState.progressHandlers[hash].remove();
458
+ delete sharedState.progressHandlers[hash];
450
459
  }
451
460
  if (__DEV__) {
452
461
  return hash;
@@ -482,7 +491,7 @@ export class Pushy {
482
491
  description,
483
492
  metaInfo,
484
493
  });
485
- Pushy.downloadedHash = hash;
494
+ sharedState.downloadedHash = hash;
486
495
  return hash;
487
496
  };
488
497
  downloadAndInstallApk = async (
@@ -492,10 +501,10 @@ export class Pushy {
492
501
  if (Platform.OS !== 'android') {
493
502
  return;
494
503
  }
495
- if (Pushy.apkStatus === 'downloading') {
504
+ if (sharedState.apkStatus === 'downloading') {
496
505
  return;
497
506
  }
498
- if (Pushy.apkStatus === 'downloaded') {
507
+ if (sharedState.apkStatus === 'downloaded') {
499
508
  this.report({ type: 'errorInstallApk' });
500
509
  this.throwIfEnabled(new Error('errorInstallApk'));
501
510
  return;
@@ -516,35 +525,36 @@ export class Pushy {
516
525
  return;
517
526
  }
518
527
  }
519
- Pushy.apkStatus = 'downloading';
528
+ sharedState.apkStatus = 'downloading';
520
529
  this.report({ type: 'downloadingApk' });
521
530
  const progressKey = 'downloadingApk';
522
531
  if (onDownloadProgress) {
523
- if (Pushy.progressHandlers[progressKey]) {
524
- Pushy.progressHandlers[progressKey].remove();
532
+ if (sharedState.progressHandlers[progressKey]) {
533
+ sharedState.progressHandlers[progressKey].remove();
525
534
  }
526
- Pushy.progressHandlers[progressKey] = pushyNativeEventEmitter.addListener(
527
- 'RCTPushyDownloadProgress',
528
- (progressData: ProgressData) => {
529
- if (progressData.hash === progressKey) {
530
- onDownloadProgress(progressData);
531
- }
532
- },
533
- );
535
+ sharedState.progressHandlers[progressKey] =
536
+ pushyNativeEventEmitter.addListener(
537
+ 'RCTPushyDownloadProgress',
538
+ (progressData: ProgressData) => {
539
+ if (progressData.hash === progressKey) {
540
+ onDownloadProgress(progressData);
541
+ }
542
+ },
543
+ );
534
544
  }
535
545
  await PushyModule.downloadAndInstallApk({
536
546
  url,
537
547
  target: 'update.apk',
538
548
  hash: progressKey,
539
549
  }).catch(() => {
540
- Pushy.apkStatus = null;
550
+ sharedState.apkStatus = null;
541
551
  this.report({ type: 'errorDownloadAndInstallApk' });
542
552
  this.throwIfEnabled(new Error('errorDownloadAndInstallApk'));
543
553
  });
544
- Pushy.apkStatus = 'downloaded';
545
- if (Pushy.progressHandlers[progressKey]) {
546
- Pushy.progressHandlers[progressKey].remove();
547
- delete Pushy.progressHandlers[progressKey];
554
+ sharedState.apkStatus = 'downloaded';
555
+ if (sharedState.progressHandlers[progressKey]) {
556
+ sharedState.progressHandlers[progressKey].remove();
557
+ delete sharedState.progressHandlers[progressKey];
548
558
  }
549
559
  };
550
560
  restartApp = async () => {
package/src/provider.tsx CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  Platform,
13
13
  Linking,
14
14
  } from 'react-native';
15
- import { Pushy, Cresc } from './client';
15
+ import { Pushy, Cresc, sharedState } from './client';
16
16
  import { currentVersion, packageVersion, getCurrentVersionInfo } from './core';
17
17
  import { CheckResult, ProgressData, UpdateTestPayload } from './type';
18
18
  import { UpdateContext } from './context';
@@ -171,7 +171,7 @@ export const UpdateProvider = ({
171
171
  return;
172
172
  }
173
173
  const rollout = info.config?.rollout?.[packageVersion];
174
- if (rollout) {
174
+ if (info.update && rollout) {
175
175
  if (!isInRollout(rollout)) {
176
176
  log(`not in ${rollout}% rollout, ignored`);
177
177
  return;
@@ -182,8 +182,15 @@ export const UpdateProvider = ({
182
182
  updateInfoRef.current = info;
183
183
  setUpdateInfo(info);
184
184
  if (info.expired) {
185
+ if (
186
+ options.onPackageExpired &&
187
+ (await options.onPackageExpired(info)) === false
188
+ ) {
189
+ log('onPackageExpired returned false, skipping');
190
+ return;
191
+ }
185
192
  const { downloadUrl } = info;
186
- if (downloadUrl && Pushy.apkStatus === null) {
193
+ if (downloadUrl && sharedState.apkStatus === null) {
187
194
  if (options.updateStrategy === 'silentAndNow') {
188
195
  if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
189
196
  downloadAndInstallApk(downloadUrl);
@@ -234,7 +241,7 @@ export const UpdateProvider = ({
234
241
  client,
235
242
  alertError,
236
243
  throwErrorIfEnabled,
237
- options.updateStrategy,
244
+ options,
238
245
  alertUpdate,
239
246
  downloadAndInstallApk,
240
247
  downloadUpdate,
package/src/type.ts CHANGED
@@ -92,6 +92,7 @@ export interface ClientOptions {
92
92
  beforeCheckUpdate?: () => Promise<boolean>;
93
93
  beforeDownloadUpdate?: (info: CheckResult) => Promise<boolean>;
94
94
  afterDownloadUpdate?: (info: CheckResult) => Promise<boolean>;
95
+ onPackageExpired?: (info: CheckResult) => Promise<boolean>;
95
96
  }
96
97
 
97
98
  export interface UpdateTestPayload {
package/src/utils.ts CHANGED
@@ -62,7 +62,7 @@ const ping =
62
62
  if (!pingFinished) {
63
63
  log('ping timeout', url);
64
64
  }
65
- }, 2000),
65
+ }, 5000),
66
66
  ),
67
67
  ]);
68
68
  };
@@ -81,6 +81,7 @@ export const testUrls = async (urls?: string[]) => {
81
81
  try {
82
82
  const ret = await promiseAny(urls.map(ping));
83
83
  if (ret) {
84
+ log('ping success, use url:', ret);
84
85
  return ret;
85
86
  }
86
87
  } catch {}
package/android/.project DELETED
@@ -1,28 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <projectDescription>
3
- <name>react-native-update</name>
4
- <comment>Project react-native-update created by Buildship.</comment>
5
- <projects>
6
- </projects>
7
- <buildSpec>
8
- <buildCommand>
9
- <name>org.eclipse.buildship.core.gradleprojectbuilder</name>
10
- <arguments>
11
- </arguments>
12
- </buildCommand>
13
- </buildSpec>
14
- <natures>
15
- <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
16
- </natures>
17
- <filteredResources>
18
- <filter>
19
- <id>1727963310481</id>
20
- <name></name>
21
- <type>30</type>
22
- <matcher>
23
- <id>org.eclipse.core.resources.regexFilterMatcher</id>
24
- <arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
25
- </matcher>
26
- </filter>
27
- </filteredResources>
28
- </projectDescription>
@@ -1,34 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <projectDescription>
3
- <name>react-native-update</name>
4
- <comment>Project react-native-update created by Buildship.</comment>
5
- <projects>
6
- </projects>
7
- <buildSpec>
8
- <buildCommand>
9
- <name>org.eclipse.jdt.core.javabuilder</name>
10
- <arguments>
11
- </arguments>
12
- </buildCommand>
13
- <buildCommand>
14
- <name>org.eclipse.buildship.core.gradleprojectbuilder</name>
15
- <arguments>
16
- </arguments>
17
- </buildCommand>
18
- </buildSpec>
19
- <natures>
20
- <nature>org.eclipse.jdt.core.javanature</nature>
21
- <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
22
- </natures>
23
- <filteredResources>
24
- <filter>
25
- <id>1727963310481</id>
26
- <name></name>
27
- <type>30</type>
28
- <matcher>
29
- <id>org.eclipse.core.resources.regexFilterMatcher</id>
30
- <arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
31
- </matcher>
32
- </filter>
33
- </filteredResources>
34
- </projectDescription>
@@ -1,13 +0,0 @@
1
- arguments=--init-script /var/folders/l6/0fn3x28s5s585ld3p04gsy1h0000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/l6/0fn3x28s5s585ld3p04gsy1h0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
2
- auto.sync=false
3
- build.scans.enabled=false
4
- connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(8.9))
5
- connection.project.dir=
6
- eclipse.preferences.version=1
7
- gradle.user.home=
8
- java.home=/Users/sunny/.sdkman/candidates/java/17.0.9-zulu/zulu-17.jdk/Contents/Home
9
- jvm.arguments=
10
- offline.mode=false
11
- override.workspace.settings=true
12
- show.console.view=true
13
- show.executions.view=true