react-native-update 10.54.0 → 10.55.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/README-CN.md +28 -0
- package/README.md +31 -1
- package/ios/RCTPushy/RCTPushy.mm +8 -1
- package/package.json +1 -1
- package/src/client.ts +136 -8
- package/src/errorReporting.ts +136 -0
- package/src/index.ts +6 -0
- package/src/type.ts +7 -0
package/README-CN.md
CHANGED
|
@@ -16,6 +16,34 @@
|
|
|
16
16
|
|
|
17
17
|
请查看[文档](https://pushy.reactnative.cn/docs/getting-started.html)
|
|
18
18
|
|
|
19
|
+
### JS 错误上报
|
|
20
|
+
|
|
21
|
+
SDK 可以把未捕获错误和手动捕获的 JavaScript 错误关联到当前实际运行的热更版本。
|
|
22
|
+
此能力默认开启、仅做尽力上报,在开发环境或启用 `disableTelemetry` 时不发送;
|
|
23
|
+
全局处理器采用链式安装,不会取代 React Native、Sentry 或 Crashlytics 已有的处理器。
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { Pushy } from 'react-native-update';
|
|
27
|
+
|
|
28
|
+
const client = new Pushy({ appKey: 'your-app-key' });
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
await submitOrder();
|
|
32
|
+
} catch (error) {
|
|
33
|
+
client.captureException(error, {
|
|
34
|
+
extra: { screen: 'checkout', retry: 1 },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 运行时显式退出(同时关闭手动 captureException 的传输):
|
|
39
|
+
client.setOptions({ disableErrorReporting: true });
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
也可以在初始化时通过 `new Pushy({ appKey, disableErrorReporting: true })` 直接退出。
|
|
43
|
+
|
|
44
|
+
只有携带明确版本 hash 的热更版本错误会被上传。上下文字段只接受经过限长的标量值;
|
|
45
|
+
不要放入密钥或个人信息。
|
|
46
|
+
|
|
19
47
|
### 优势
|
|
20
48
|
|
|
21
49
|
1. 对中国用户使用阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。海外用户智能分流至 cloudflare,同样提供稳定高速的分发体验。
|
package/README.md
CHANGED
|
@@ -14,6 +14,37 @@ See the docs:
|
|
|
14
14
|
|
|
15
15
|
- English docs: <https://cresc.dev/docs/getting-started>
|
|
16
16
|
|
|
17
|
+
## JS error reporting
|
|
18
|
+
|
|
19
|
+
The SDK reports uncaught and manually captured JavaScript errors against the
|
|
20
|
+
currently running OTA release. Reporting is enabled by default, best-effort,
|
|
21
|
+
disabled in development and when `disableTelemetry` is enabled, and never
|
|
22
|
+
replaces an existing React Native, Sentry or Crashlytics global handler.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { Cresc } from 'react-native-update';
|
|
26
|
+
|
|
27
|
+
const client = new Cresc({ appKey: 'your-app-key' });
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
await submitOrder();
|
|
31
|
+
} catch (error) {
|
|
32
|
+
client.captureException(error, {
|
|
33
|
+
extra: { screen: 'checkout', retry: 1 },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Explicit runtime opt-out (also disables manual captureException transport):
|
|
38
|
+
client.setOptions({ disableErrorReporting: true });
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
You can also opt out at construction with
|
|
42
|
+
`new Cresc({ appKey, disableErrorReporting: true })`.
|
|
43
|
+
|
|
44
|
+
Only errors from an OTA version with a known version hash are uploaded. Context
|
|
45
|
+
is deliberately restricted to bounded scalar values; do not include secrets or
|
|
46
|
+
personal information.
|
|
47
|
+
|
|
17
48
|
## Advantages
|
|
18
49
|
|
|
19
50
|
1. react-native-update provides a dedicated global service with fast and reliable worldwide delivery.
|
|
@@ -85,4 +116,3 @@ Since 10.52.1 every cold start runs one background update check that **does not
|
|
|
85
116
|
| **Technical Support** | ✅ Paid dedicated support | ⚠️ Community support | ❌ **Discontinued** |
|
|
86
117
|
| **Server Deployment** | ✅ Hosted service or paid private deployment | ✅ Hosted by Expo (EAS Update) | ❌ **Discontinued** |
|
|
87
118
|
| **Bandwidth Usage** | ⭐⭐⭐⭐⭐ Very low (incremental) | ⭐⭐⭐ Higher (full bundle) | ❌ **Discontinued** |
|
|
88
|
-
|
package/ios/RCTPushy/RCTPushy.mm
CHANGED
|
@@ -14,8 +14,15 @@
|
|
|
14
14
|
|
|
15
15
|
#import <UIKit/UIKit.h>
|
|
16
16
|
|
|
17
|
+
// use_frameworks! 构建里 React 头文件只有 <React/…> 框架形式可见,引号形式的
|
|
18
|
+
// __has_include 会探测失败;漏掉这里会静默编入 [self.bridge reload] 兜底,而
|
|
19
|
+
// bridgeless 下 bridge 是 nil/代理,reload 变成无声 no-op(切版本后不重启)。
|
|
17
20
|
#if __has_include("RCTReloadCommand.h")
|
|
18
21
|
#import "RCTReloadCommand.h"
|
|
22
|
+
#define PUSHY_HAS_RELOAD_COMMAND 1
|
|
23
|
+
#elif __has_include(<React/RCTReloadCommand.h>)
|
|
24
|
+
#import <React/RCTReloadCommand.h>
|
|
25
|
+
#define PUSHY_HAS_RELOAD_COMMAND 1
|
|
19
26
|
#endif
|
|
20
27
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
21
28
|
#import "RCTPushySpec.h"
|
|
@@ -1256,7 +1263,7 @@ RCT_EXPORT_METHOD(resetToPackagedBundle:(RCTPromiseResolveBlock)resolve
|
|
|
1256
1263
|
- (void)reloadBridgeWithReason:(NSString *)reason
|
|
1257
1264
|
{
|
|
1258
1265
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1259
|
-
#if
|
|
1266
|
+
#if PUSHY_HAS_RELOAD_COMMAND
|
|
1260
1267
|
RCTReloadCommandSetBundleURL([[self class] bundleURL]);
|
|
1261
1268
|
RCTTriggerReloadCommandListeners(reason);
|
|
1262
1269
|
#else
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -25,6 +25,13 @@ import {
|
|
|
25
25
|
UpdateError,
|
|
26
26
|
type UpdateErrorCode,
|
|
27
27
|
} from './error';
|
|
28
|
+
import {
|
|
29
|
+
type ErrorReportContext,
|
|
30
|
+
type ErrorReportingOptions,
|
|
31
|
+
installGlobalErrorHandler,
|
|
32
|
+
type SerializedException,
|
|
33
|
+
serializeException,
|
|
34
|
+
} from './errorReporting';
|
|
28
35
|
import i18n from './i18n';
|
|
29
36
|
import {
|
|
30
37
|
resolveServerEventHash,
|
|
@@ -78,10 +85,6 @@ const SERVER_PRESETS = {
|
|
|
78
85
|
main: [
|
|
79
86
|
'https://update.react-native.cn/api',
|
|
80
87
|
'https://update.reactnative.cn/api',
|
|
81
|
-
'https://1.rnupdate.online/api',
|
|
82
|
-
'https://2.rnupdate.online/api',
|
|
83
|
-
'https://3.rnupdate.online/api',
|
|
84
|
-
'https://4.rnupdate.online/api',
|
|
85
88
|
],
|
|
86
89
|
queryUrls: [
|
|
87
90
|
'https://gitee.com/sunnylqm/react-native-pushy/raw/master/endpoints.json',
|
|
@@ -125,6 +128,7 @@ const createDefaultClientOptions = (): ClientOptions => ({
|
|
|
125
128
|
logger: noop,
|
|
126
129
|
debug: false,
|
|
127
130
|
throwError: false,
|
|
131
|
+
disableErrorReporting: false,
|
|
128
132
|
});
|
|
129
133
|
|
|
130
134
|
export const sharedState: {
|
|
@@ -182,6 +186,8 @@ export class Pushy {
|
|
|
182
186
|
private pendingNativeConfigJson?: string;
|
|
183
187
|
private nativeConfigSyncInFlight = false;
|
|
184
188
|
private reportedInvalidUpdates = new Set<string>();
|
|
189
|
+
private reportedExceptions = new WeakSet<object>();
|
|
190
|
+
private globalErrorCleanup?: () => void;
|
|
185
191
|
|
|
186
192
|
version = cInfo.rnu;
|
|
187
193
|
loggerPromise = (() => {
|
|
@@ -280,9 +286,18 @@ export class Pushy {
|
|
|
280
286
|
log('onOptionsChange listener error:', e?.message || e);
|
|
281
287
|
}
|
|
282
288
|
}
|
|
289
|
+
this.syncAutomaticErrorReporting();
|
|
283
290
|
this.syncNativeConfig();
|
|
284
291
|
};
|
|
285
292
|
|
|
293
|
+
private syncAutomaticErrorReporting = (): void => {
|
|
294
|
+
if (this.options.disableTelemetry || this.options.disableErrorReporting) {
|
|
295
|
+
this.globalErrorCleanup?.();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
this.enableErrorReporting();
|
|
299
|
+
};
|
|
300
|
+
|
|
286
301
|
/** Build the subset of options used by the native cold-start check. */
|
|
287
302
|
private getNativeConfig = (): Record<string, unknown> | undefined => {
|
|
288
303
|
if (
|
|
@@ -518,6 +533,115 @@ export class Pushy {
|
|
|
518
533
|
});
|
|
519
534
|
};
|
|
520
535
|
|
|
536
|
+
/**
|
|
537
|
+
* Best-effort JS exception reporting for the currently running OTA release.
|
|
538
|
+
* It is intentionally synchronous to call and never throws; the transport
|
|
539
|
+
* runs in the background and preserves the app's existing error flow.
|
|
540
|
+
*/
|
|
541
|
+
captureException = (
|
|
542
|
+
error: unknown,
|
|
543
|
+
context: ErrorReportContext = {}
|
|
544
|
+
): void => {
|
|
545
|
+
try {
|
|
546
|
+
if (
|
|
547
|
+
__DEV__ ||
|
|
548
|
+
this.options.disableTelemetry ||
|
|
549
|
+
this.options.disableErrorReporting
|
|
550
|
+
) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (
|
|
554
|
+
error !== null &&
|
|
555
|
+
(typeof error === 'object' || typeof error === 'function')
|
|
556
|
+
) {
|
|
557
|
+
const object = error as object;
|
|
558
|
+
if (this.reportedExceptions.has(object)) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
this.reportedExceptions.add(object);
|
|
562
|
+
}
|
|
563
|
+
this.reportExceptionToServer(serializeException(error, context));
|
|
564
|
+
} catch (e: any) {
|
|
565
|
+
log('exception telemetry error:', e?.message || e);
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Ensure uncaught JS exception capture is installed and return a runtime
|
|
571
|
+
* cleanup function. Capture is installed automatically by default; this
|
|
572
|
+
* method remains an idempotent compatibility hook. The wrapper always
|
|
573
|
+
* chains the handler that was installed before it and only restores that
|
|
574
|
+
* handler when no later integration has replaced ours.
|
|
575
|
+
*/
|
|
576
|
+
enableErrorReporting = (
|
|
577
|
+
options: ErrorReportingOptions = {}
|
|
578
|
+
): (() => void) => {
|
|
579
|
+
if (
|
|
580
|
+
options.captureGlobal === false ||
|
|
581
|
+
this.options.disableTelemetry ||
|
|
582
|
+
this.options.disableErrorReporting
|
|
583
|
+
) {
|
|
584
|
+
return () => {};
|
|
585
|
+
}
|
|
586
|
+
if (this.globalErrorCleanup) {
|
|
587
|
+
return this.globalErrorCleanup;
|
|
588
|
+
}
|
|
589
|
+
const uninstall = installGlobalErrorHandler((error, isFatal) => {
|
|
590
|
+
this.captureException(error, { fatal: isFatal === true });
|
|
591
|
+
});
|
|
592
|
+
let active = true;
|
|
593
|
+
const cleanup = () => {
|
|
594
|
+
if (!active) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
active = false;
|
|
598
|
+
uninstall();
|
|
599
|
+
if (this.globalErrorCleanup === cleanup) {
|
|
600
|
+
this.globalErrorCleanup = undefined;
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
this.globalErrorCleanup = cleanup;
|
|
604
|
+
return cleanup;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
private reportExceptionToServer = (error: SerializedException): void => {
|
|
608
|
+
try {
|
|
609
|
+
if (
|
|
610
|
+
__DEV__ ||
|
|
611
|
+
this.options.disableTelemetry ||
|
|
612
|
+
this.options.disableErrorReporting ||
|
|
613
|
+
!currentVersion
|
|
614
|
+
) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const { appKey } = this.options;
|
|
618
|
+
const endpoint =
|
|
619
|
+
this.lastWorkingEndpoint || this.options.server?.main?.[0];
|
|
620
|
+
if (!appKey || !endpoint) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
fetchWithTimeout(
|
|
624
|
+
`${endpoint}/report/${appKey}`,
|
|
625
|
+
{
|
|
626
|
+
method: 'POST',
|
|
627
|
+
headers: { 'Content-Type': 'application/json' },
|
|
628
|
+
body: JSON.stringify({
|
|
629
|
+
type: 'js_exception',
|
|
630
|
+
hash: currentVersion,
|
|
631
|
+
packageVersion: this.getEffectivePackageVersion(),
|
|
632
|
+
cInfo,
|
|
633
|
+
error,
|
|
634
|
+
}),
|
|
635
|
+
},
|
|
636
|
+
DEFAULT_FETCH_TIMEOUT_MS
|
|
637
|
+
).catch((e: any) => {
|
|
638
|
+
log('exception telemetry report failed:', e?.message || e);
|
|
639
|
+
});
|
|
640
|
+
} catch (e: any) {
|
|
641
|
+
log('exception telemetry error:', e?.message || e);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
|
|
521
645
|
report = async ({
|
|
522
646
|
type,
|
|
523
647
|
message = '',
|
|
@@ -1167,6 +1291,14 @@ export class Pushy {
|
|
|
1167
1291
|
) => {
|
|
1168
1292
|
const { name, description = '', metaInfo } = updateInfo;
|
|
1169
1293
|
const { hash, attempts, devNoop } = plan;
|
|
1294
|
+
if (devNoop) {
|
|
1295
|
+
// Dev without a full package URL: nothing can be fetched, let alone
|
|
1296
|
+
// installed. Say so and deliver nothing — faking a success here used to
|
|
1297
|
+
// hand the caller a hash whose switchVersion the native side (rightly)
|
|
1298
|
+
// rejects with SWITCH_VERSION_FAILED.
|
|
1299
|
+
log(this.t('dev_incremental_update_disabled'));
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1170
1302
|
const patchStartTime = Date.now();
|
|
1171
1303
|
// One native listener per hash dispatching to a callback set, so
|
|
1172
1304
|
// concurrent callers deduped onto this task can each observe progress
|
|
@@ -1272,10 +1404,6 @@ export class Pushy {
|
|
|
1272
1404
|
attempt,
|
|
1273
1405
|
},
|
|
1274
1406
|
});
|
|
1275
|
-
if (devNoop) {
|
|
1276
|
-
log(this.t('dev_incremental_update_disabled'));
|
|
1277
|
-
succeeded = 'full';
|
|
1278
|
-
}
|
|
1279
1407
|
for (const { type, urls } of attempts) {
|
|
1280
1408
|
if (succeeded) {
|
|
1281
1409
|
break;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export type ErrorContextValue = string | number | boolean | null;
|
|
2
|
+
|
|
3
|
+
export interface ErrorReportContext {
|
|
4
|
+
fatal?: boolean;
|
|
5
|
+
componentStack?: string;
|
|
6
|
+
extra?: Record<string, ErrorContextValue>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ErrorReportingOptions {
|
|
10
|
+
/** Install a chained React Native ErrorUtils handler. Default: true. */
|
|
11
|
+
captureGlobal?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SerializedException {
|
|
15
|
+
name: string;
|
|
16
|
+
message: string;
|
|
17
|
+
stack: string;
|
|
18
|
+
fatal: boolean;
|
|
19
|
+
componentStack?: string;
|
|
20
|
+
extra?: Record<string, ErrorContextValue>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const MAX_NAME = 128;
|
|
24
|
+
const MAX_MESSAGE = 2 * 1024;
|
|
25
|
+
const MAX_STACK = 32 * 1024;
|
|
26
|
+
const MAX_COMPONENT_STACK = 16 * 1024;
|
|
27
|
+
const MAX_EXTRA_FIELDS = 32;
|
|
28
|
+
const MAX_EXTRA_KEY = 64;
|
|
29
|
+
const MAX_EXTRA_STRING = 1024;
|
|
30
|
+
const MAX_EXTRA_JSON = 8 * 1024;
|
|
31
|
+
|
|
32
|
+
const boundedString = (value: unknown, maximum: number) =>
|
|
33
|
+
typeof value === 'string' ? value.slice(0, maximum) : '';
|
|
34
|
+
|
|
35
|
+
const normalizeExtra = (
|
|
36
|
+
extra?: Record<string, ErrorContextValue>
|
|
37
|
+
): Record<string, ErrorContextValue> | undefined => {
|
|
38
|
+
if (!extra || typeof extra !== 'object') {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const result: Record<string, ErrorContextValue> = {};
|
|
42
|
+
for (const [rawKey, value] of Object.entries(extra).slice(
|
|
43
|
+
0,
|
|
44
|
+
MAX_EXTRA_FIELDS
|
|
45
|
+
)) {
|
|
46
|
+
const key = rawKey.slice(0, MAX_EXTRA_KEY);
|
|
47
|
+
if (!key) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === 'string') {
|
|
51
|
+
result[key] = value.slice(0, MAX_EXTRA_STRING);
|
|
52
|
+
} else if (
|
|
53
|
+
value === null ||
|
|
54
|
+
typeof value === 'boolean' ||
|
|
55
|
+
(typeof value === 'number' && Number.isFinite(value))
|
|
56
|
+
) {
|
|
57
|
+
result[key] = value;
|
|
58
|
+
}
|
|
59
|
+
// Keep the client comfortably inside the server's byte cap. The server
|
|
60
|
+
// remains authoritative because JS string length is not UTF-8 byte length.
|
|
61
|
+
if (JSON.stringify(result).length > MAX_EXTRA_JSON) {
|
|
62
|
+
delete result[key];
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const serializeException = (
|
|
70
|
+
error: unknown,
|
|
71
|
+
context: ErrorReportContext = {}
|
|
72
|
+
): SerializedException => {
|
|
73
|
+
const source =
|
|
74
|
+
error !== null && (typeof error === 'object' || typeof error === 'function')
|
|
75
|
+
? (error as Record<string, unknown>)
|
|
76
|
+
: undefined;
|
|
77
|
+
const name = boundedString(source?.name, MAX_NAME).trim() || 'Error';
|
|
78
|
+
const message = (
|
|
79
|
+
boundedString(source?.message, MAX_MESSAGE) || String(error ?? '')
|
|
80
|
+
).slice(0, MAX_MESSAGE);
|
|
81
|
+
const stack =
|
|
82
|
+
boundedString(source?.stack, MAX_STACK) || `${name}: ${message}`;
|
|
83
|
+
const componentStack = boundedString(
|
|
84
|
+
context.componentStack,
|
|
85
|
+
MAX_COMPONENT_STACK
|
|
86
|
+
);
|
|
87
|
+
const extra = normalizeExtra(context.extra);
|
|
88
|
+
return {
|
|
89
|
+
name,
|
|
90
|
+
message,
|
|
91
|
+
stack,
|
|
92
|
+
fatal: context.fatal === true,
|
|
93
|
+
...(componentStack ? { componentStack } : {}),
|
|
94
|
+
...(extra ? { extra } : {}),
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
type GlobalErrorHandler = (error: unknown, isFatal?: boolean) => void;
|
|
99
|
+
|
|
100
|
+
interface GlobalErrorUtils {
|
|
101
|
+
getGlobalHandler?: () => GlobalErrorHandler;
|
|
102
|
+
setGlobalHandler?: (handler: GlobalErrorHandler) => void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Install a React Native global error wrapper without taking ownership away
|
|
107
|
+
* from ExceptionsManager, Sentry, Crashlytics, or a handler installed later.
|
|
108
|
+
*/
|
|
109
|
+
export const installGlobalErrorHandler = (
|
|
110
|
+
capture: GlobalErrorHandler
|
|
111
|
+
): (() => void) => {
|
|
112
|
+
const errorUtils = (globalThis as any).ErrorUtils as
|
|
113
|
+
| GlobalErrorUtils
|
|
114
|
+
| undefined;
|
|
115
|
+
if (
|
|
116
|
+
typeof errorUtils?.getGlobalHandler !== 'function' ||
|
|
117
|
+
typeof errorUtils.setGlobalHandler !== 'function'
|
|
118
|
+
) {
|
|
119
|
+
return () => {};
|
|
120
|
+
}
|
|
121
|
+
const previous = errorUtils.getGlobalHandler();
|
|
122
|
+
const wrapper: GlobalErrorHandler = (error, isFatal) => {
|
|
123
|
+
try {
|
|
124
|
+
capture(error, isFatal);
|
|
125
|
+
} catch {
|
|
126
|
+
// Reporting must never alter React Native's original failure path.
|
|
127
|
+
}
|
|
128
|
+
previous?.(error, isFatal);
|
|
129
|
+
};
|
|
130
|
+
errorUtils.setGlobalHandler(wrapper);
|
|
131
|
+
return () => {
|
|
132
|
+
if (errorUtils.getGlobalHandler?.() === wrapper) {
|
|
133
|
+
errorUtils.setGlobalHandler?.(previous);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,12 @@ export {
|
|
|
10
10
|
export { PushyModule, UpdateModule } from './core';
|
|
11
11
|
export type { UpdateErrorCode } from './error';
|
|
12
12
|
export { UpdateError } from './error';
|
|
13
|
+
export type {
|
|
14
|
+
ErrorContextValue,
|
|
15
|
+
ErrorReportContext,
|
|
16
|
+
ErrorReportingOptions,
|
|
17
|
+
SerializedException,
|
|
18
|
+
} from './errorReporting';
|
|
13
19
|
export type { CrashReporterLike, UpdateMetadata } from './metadata';
|
|
14
20
|
export {
|
|
15
21
|
attachToCrashlytics,
|
package/src/type.ts
CHANGED
|
@@ -205,6 +205,13 @@ export interface ClientOptions {
|
|
|
205
205
|
* the version health view in the console. Default: false (enabled).
|
|
206
206
|
*/
|
|
207
207
|
disableTelemetry?: boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Disable automatic and manual JavaScript exception reporting. Reporting is
|
|
210
|
+
* enabled by default and chains React Native's existing global ErrorUtils
|
|
211
|
+
* handler. Set this to true for an explicit opt-out; update lifecycle
|
|
212
|
+
* telemetry remains controlled separately by `disableTelemetry`.
|
|
213
|
+
*/
|
|
214
|
+
disableErrorReporting?: boolean;
|
|
208
215
|
/**
|
|
209
216
|
* Disable the native cold-start update check: the background check that runs
|
|
210
217
|
* a few seconds after every launch, independent of JS
|