sentry-miniapp 1.2.0 → 1.4.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/CHANGELOG.md +123 -0
- package/README.md +113 -0
- package/dist/sentry-miniapp.cjs.js +187 -39
- package/dist/sentry-miniapp.cjs.js.map +1 -1
- package/dist/sentry-miniapp.esm.js +187 -39
- package/dist/sentry-miniapp.esm.js.map +1 -1
- package/dist/sentry-miniapp.umd.js +187 -39
- package/dist/sentry-miniapp.umd.js.map +1 -1
- package/dist/types/client.d.ts +4 -6
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/integrations/index.d.ts +2 -0
- package/dist/types/integrations/index.d.ts.map +1 -1
- package/dist/types/integrations/networkbreadcrumbs.d.ts +29 -0
- package/dist/types/integrations/networkbreadcrumbs.d.ts.map +1 -0
- package/dist/types/integrations/rewriteframes.d.ts +35 -0
- package/dist/types/integrations/rewriteframes.d.ts.map +1 -0
- package/dist/types/sdk.d.ts +6 -4
- package/dist/types/sdk.d.ts.map +1 -1
- package/dist/types/transports/offlineStore.d.ts +4 -1
- package/dist/types/transports/offlineStore.d.ts.map +1 -1
- package/dist/types/types.d.ts +6 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +94 -16
- package/src/.keep +0 -0
- package/src/client.ts +203 -0
- package/src/crossPlatform.ts +407 -0
- package/src/eventbuilder.ts +291 -0
- package/src/helpers.ts +214 -0
- package/src/index.ts +86 -0
- package/src/integrations/dedupe.ts +215 -0
- package/src/integrations/globalhandlers.ts +209 -0
- package/src/integrations/httpcontext.ts +140 -0
- package/src/integrations/index.ts +10 -0
- package/src/integrations/linkederrors.ts +107 -0
- package/src/integrations/networkbreadcrumbs.ts +155 -0
- package/src/integrations/performance.ts +622 -0
- package/src/integrations/rewriteframes.ts +77 -0
- package/src/integrations/router.ts +180 -0
- package/src/integrations/system.ts +135 -0
- package/src/integrations/trycatch.ts +233 -0
- package/src/polyfills.ts +242 -0
- package/src/sdk.ts +182 -0
- package/src/transports/index.ts +3 -0
- package/src/transports/offlineStore.ts +85 -0
- package/src/transports/xhr.ts +68 -0
- package/src/types.ts +129 -0
- package/src/version.ts +3 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# 更新日志
|
|
2
|
+
|
|
3
|
+
本文档记录了 sentry-miniapp 项目的所有重要变更。
|
|
4
|
+
|
|
5
|
+
## [1.4.0] - 2026-03-23
|
|
6
|
+
|
|
7
|
+
### 新增
|
|
8
|
+
|
|
9
|
+
- ✨ 新增 `NetworkBreadcrumbs` 集成:支持抓取网络请求的 Request Body 和 Response Body。通过 `traceNetworkBody: true` 开启,方便深度排查接口异常。
|
|
10
|
+
- ✨ 离线缓存上限可配置:在 `Sentry.init` 中新增 `offlineCacheLimit` 选项,允许开发者根据业务场景调大离线重试队列(默认 30)。
|
|
11
|
+
- 🚀 支持全平台自动构建同步:重构构建脚本,`npm run build` 现在会自动将产物同步至示例工程,提升本地开发和直接拷贝单文件用户的体验。
|
|
12
|
+
|
|
13
|
+
### 修复 & 优化
|
|
14
|
+
|
|
15
|
+
- 🐛 修复无限死循环:在 `NetworkBreadcrumbs` 中自动忽略了配置的自托管(Self-Hosted)Sentry DSN 域名以及 `sentry.io`,防止上报请求被拦截。
|
|
16
|
+
- 🗑️ 废弃 `showReportDialog`:小程序环境不支持 Sentry 官方 HTML 弹窗,已废弃该方法并输出清晰的警告,文档中增加了自定义 UI + `captureFeedback` 的最佳实践。
|
|
17
|
+
- 📦 优化主包体积说明:在 README 中增加了关于“利用分包异步化实现 0KB 主包占用”的详细指南。
|
|
18
|
+
- 🔍 优化 NPM 发现率:补充了全量的小程序平台和跨端框架中英文关键词。
|
|
19
|
+
- 📚 文档精简:合并并删除了冗余的 `DEVELOPMENT_GUIDE.md`。
|
|
20
|
+
|
|
21
|
+
## [1.3.1] - 2026-03-23
|
|
22
|
+
|
|
23
|
+
### 修复
|
|
24
|
+
|
|
25
|
+
- 🐛 修复事件上报中出现大量 `undefined` 值的问题
|
|
26
|
+
- 🔧 改进系统信息收集逻辑,为所有可能为 undefined 的字段提供默认值
|
|
27
|
+
- ✅ 增强 `getSystemInfo` 函数的健壮性,确保返回的数据结构完整
|
|
28
|
+
- 🎯 改进事件构建器中的系统信息处理,提供完整的回退机制
|
|
29
|
+
|
|
30
|
+
### 新增
|
|
31
|
+
|
|
32
|
+
- 🧪 新增系统信息处理的测试用例,验证 undefined 字段的处理
|
|
33
|
+
- 🧪 新增系统信息不可用时的回退值测试
|
|
34
|
+
|
|
35
|
+
## [1.0.1-beta.1] - 2025-01-07
|
|
36
|
+
|
|
37
|
+
### 修复
|
|
38
|
+
|
|
39
|
+
- 🐛 修复 Performance API 集成中的 TypeError 错误 (`entries.forEach is not a function`)
|
|
40
|
+
- 🔧 为不同的 PerformanceObserver 回调参数格式添加健壮处理
|
|
41
|
+
- ✅ 改进与微信小程序 PerformanceObserver 实现的兼容性
|
|
42
|
+
|
|
43
|
+
### 改进
|
|
44
|
+
|
|
45
|
+
- 🎯 增强 `_handlePerformanceEntries` 方法以处理各种条目格式:
|
|
46
|
+
- 标准数组格式
|
|
47
|
+
- 单个对象格式
|
|
48
|
+
- PerformanceObserverEntryList 类对象
|
|
49
|
+
- 无效/null 参数(优雅处理)
|
|
50
|
+
|
|
51
|
+
### 新增
|
|
52
|
+
|
|
53
|
+
- 🧪 为不同 Performance API 条目格式添加额外测试用例
|
|
54
|
+
|
|
55
|
+
## [未发布]
|
|
56
|
+
|
|
57
|
+
### 新增
|
|
58
|
+
|
|
59
|
+
- ✅ 大幅提升测试覆盖率,新增 274+ 测试用例
|
|
60
|
+
- 🧪 新增 `crossPlatform.test.ts` - 测试平台检测、SDK获取和系统信息功能
|
|
61
|
+
- 🧪 新增 `eventbuilder.test.ts` - 测试事件构建、异常处理和消息格式化
|
|
62
|
+
- 🧪 新增 `polyfills.test.ts` - 测试 polyfill 功能
|
|
63
|
+
- 🧪 新增 `version.test.ts` - 测试版本信息导出
|
|
64
|
+
- 🧪 新增 `dedupe.test.ts` - 测试去重集成功能
|
|
65
|
+
- 🧪 新增 `router.test.ts` - 测试路由集成功能
|
|
66
|
+
- 📁 新增 `integration-tests/` 目录 - 包含端到端集成测试
|
|
67
|
+
- 🔧 新增开发模式监听构建 (`npm run dev`)
|
|
68
|
+
- 📚 完善开发文档和贡献指南
|
|
69
|
+
|
|
70
|
+
### 改进
|
|
71
|
+
|
|
72
|
+
- 🧪 增强 `helpers.test.ts` - 补充更多工具函数测试
|
|
73
|
+
- 🔧 修复测试隔离问题 - 解决模块缓存导致的测试干扰
|
|
74
|
+
- 🎯 优化测试结构 - 改进异步导入和测试期望值
|
|
75
|
+
- 📝 更新 README.md - 反映最新功能和测试状态
|
|
76
|
+
- 📝 更新 DEVELOPMENT.md - 添加测试和质量保证指南
|
|
77
|
+
- 🏗️ 改进构建配置 - 支持开发和生产模式
|
|
78
|
+
|
|
79
|
+
### 移除
|
|
80
|
+
|
|
81
|
+
- 🗑️ 清理过时文件 - 移除 `test-scripts` 目录下的调试脚本
|
|
82
|
+
- 🧹 重构测试脚本 - 将调试脚本移至 `integration-tests` 目录
|
|
83
|
+
|
|
84
|
+
### 修复
|
|
85
|
+
|
|
86
|
+
- 🐛 修复 `crossPlatform.test.ts` 中的测试失败问题
|
|
87
|
+
- 🐛 解决模块缓存导致的测试隔离问题
|
|
88
|
+
- 🔧 修复 TypeScript 类型错误
|
|
89
|
+
- ✅ 确保所有测试稳定通过
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 版本说明
|
|
94
|
+
|
|
95
|
+
### 语义化版本控制
|
|
96
|
+
|
|
97
|
+
本项目遵循 [语义化版本控制](https://semver.org/lang/zh-CN/) 规范:
|
|
98
|
+
|
|
99
|
+
- **主版本号**:不兼容的 API 修改
|
|
100
|
+
- **次版本号**:向下兼容的功能性新增
|
|
101
|
+
- **修订号**:向下兼容的问题修正
|
|
102
|
+
|
|
103
|
+
### 变更类型
|
|
104
|
+
|
|
105
|
+
- **新增** - 新功能
|
|
106
|
+
- **改进** - 对现有功能的改进
|
|
107
|
+
- **修复** - 问题修复
|
|
108
|
+
- **移除** - 移除的功能
|
|
109
|
+
- **安全** - 安全相关的修复
|
|
110
|
+
- **废弃** - 即将移除的功能
|
|
111
|
+
|
|
112
|
+
### 图标说明
|
|
113
|
+
|
|
114
|
+
- ✅ 完成的功能
|
|
115
|
+
- 🧪 测试相关
|
|
116
|
+
- 🔧 开发工具
|
|
117
|
+
- 📚 文档
|
|
118
|
+
- 🐛 Bug 修复
|
|
119
|
+
- 🎯 性能优化
|
|
120
|
+
- 🏗️ 构建系统
|
|
121
|
+
- 📁 文件结构
|
|
122
|
+
- 🗑️ 删除
|
|
123
|
+
- 🧹 重构
|
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
- **📱 真正的多端支持**:内置 API 抹平引擎,一套代码无缝兼容**微信、支付宝、字节、百度、QQ、钉钉、快手**等主流小程序平台。
|
|
23
23
|
- **🎯 全自动异常捕获**:无需侵入业务代码,自动监听并上报生命周期异常(`onError`、`onUnhandledRejection`、`onPageNotFound`、`onMemoryWarning`)。
|
|
24
24
|
- **🍞 丰富的上下文面包屑**:自动记录设备信息、用户点击/触摸操作、网络请求(XHR/Fetch)、以及页面路由导航路径。
|
|
25
|
+
- **🗺️ 内置 SourceMap 路径抹平**:自动处理微信、支付宝、字节等多端小程序的虚拟堆栈路径,配合 sentry-cli 极简实现 SourceMap 解析。
|
|
25
26
|
- **📡 弱网离线缓存机制**:专为小程序网络环境设计,断网或发送失败时自动缓存 Event 到本地 Storage,网络恢复后静默重试上报,确保数据不丢失。
|
|
26
27
|
- **⚡ 深度性能监控**:集成小程序 Performance API,全面采集导航性能(FCP/LCP)、渲染性能、资源加载耗时及用户自定义性能标记。
|
|
27
28
|
- **�️ 智能降噪与过滤**:内置强大的错误去重和采样率控制机制,避免日志风暴。
|
|
@@ -67,9 +68,14 @@ Sentry.init({
|
|
|
67
68
|
enableSystemInfo: true, // 自动采集系统与设备信息
|
|
68
69
|
enableUserInteractionBreadcrumbs: true, // 自动记录用户点击行为
|
|
69
70
|
enableNavigationBreadcrumbs: true, // 自动记录页面路由跳转
|
|
71
|
+
traceNetworkBody: true, // [新增] 是否在面包屑中记录网络请求的请求体和响应体 (默认 false)
|
|
70
72
|
|
|
71
73
|
// --- 离线缓存与可靠性 ---
|
|
72
74
|
enableOfflineCache: true, // 开启断网离线缓存与重试机制 (默认开启)
|
|
75
|
+
offlineCacheLimit: 30, // 离线缓存的最大事件数 (默认 30,可调大以防弱网下丢失更多数据)
|
|
76
|
+
|
|
77
|
+
// --- SourceMap 支持 ---
|
|
78
|
+
enableSourceMap: true, // 开启自动将堆栈的虚拟路径转为统一格式,配合上传 sourcemap 时的 --url-prefix "app:///"
|
|
73
79
|
|
|
74
80
|
// --- 性能与采样率 ---
|
|
75
81
|
sampleRate: 1.0, // 异常上报采样率 (0.0 - 1.0)
|
|
@@ -147,6 +153,113 @@ Sentry.measurePerformance('fetch-user-data', 'api-request-start', 'api-request-e
|
|
|
147
153
|
|
|
148
154
|
---
|
|
149
155
|
|
|
156
|
+
## 🗺️ Source Map 支持与配置
|
|
157
|
+
|
|
158
|
+
在小程序中,报错堆栈的路径通常是各种虚拟路径(如 `appservice/pages/index.js`),这导致直接上传的 Source Map 无法被 Sentry 正确解析。
|
|
159
|
+
|
|
160
|
+
SDK 内部已经为您解决了这个痛点:
|
|
161
|
+
只要在 `Sentry.init` 时开启了 `enableSourceMap: true`(默认开启),SDK 会在报错时自动拦截并抹平各平台的虚拟路径,统一替换为标准前缀 `app:///`。
|
|
162
|
+
|
|
163
|
+
您**只需要在打包上传 Source Map 时,确保配置的 `url-prefix` 为 `app:///` 即可**。
|
|
164
|
+
|
|
165
|
+
**使用 sentry-cli 上传示例:**
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
sentry-cli releases files "your-project-release-id" upload-sourcemaps ./dist \
|
|
169
|
+
--url-prefix "app:///" \
|
|
170
|
+
--ext .js --ext .map
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
*(注:在微信开发者工具上传代码时,请**务必关闭**工具自带的“ES6转ES5”和“代码压缩”功能,将这些工作交给 Webpack/Vite 等构建工具,以防行列号错位。)*
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 💬 用户反馈 (User Feedback)
|
|
178
|
+
|
|
179
|
+
在 Web 环境中,Sentry 提供了一个现成的 `showReportDialog()` 弹窗。但在小程序环境中没有 DOM 无法直接渲染该组件,因此 `showReportDialog()` 已被**废弃**。
|
|
180
|
+
|
|
181
|
+
请您**自行实现一个原生小程序表单(或弹窗)**来收集用户的反馈信息,然后调用 `Sentry.captureFeedback()` 提交到 Sentry 后台:
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
// 当发生错误,或者用户主动点击“反馈”按钮时,展示您自己画的表单:
|
|
185
|
+
const userMessage = '页面卡住了,点什么都没反应';
|
|
186
|
+
const userName = '张三';
|
|
187
|
+
const userEmail = 'zhangsan@example.com';
|
|
188
|
+
|
|
189
|
+
// 将收集到的反馈发送给 Sentry
|
|
190
|
+
Sentry.captureFeedback({
|
|
191
|
+
message: userMessage,
|
|
192
|
+
name: userName,
|
|
193
|
+
email: userEmail,
|
|
194
|
+
// 选填:如果您想把这个反馈和某个具体的错误事件关联起来:
|
|
195
|
+
// associatedEventId: 'abc123xyz...'
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 📦 主包体积优化 (0KB 主包占用方案)
|
|
202
|
+
|
|
203
|
+
小程序的“主包体积”非常宝贵(通常限制在 2MB 以内)。`sentry-miniapp` 由于集成了完整的 `@sentry/core` 核心引擎和多端适配,原始体积约在 200KB 左右。
|
|
204
|
+
|
|
205
|
+
如果您非常在意主包体积,**强烈建议使用平台提供的「分包异步化」或「动态加载」特性**,将 SDK 的体积完全转移到分包中。
|
|
206
|
+
|
|
207
|
+
### 方案 A:微信 / 支付宝小程序(推荐)
|
|
208
|
+
|
|
209
|
+
微信和支付宝等平台原生支持[分包异步化](https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/async.html)。
|
|
210
|
+
|
|
211
|
+
**具体操作步骤:**
|
|
212
|
+
|
|
213
|
+
1. 将 `sentry-miniapp` 的 npm 包或者构建后的文件放入您的某个分包目录中(例如 `subpackageA`)。
|
|
214
|
+
2. 在您的 `app.js` 顶部,使用 `require.async` 异步懒加载 SDK 并进行初始化:
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
// app.js
|
|
218
|
+
App({
|
|
219
|
+
onLaunch() {
|
|
220
|
+
// 异步加载分包中的 sentry
|
|
221
|
+
require.async('./subpackageA/sentry-miniapp.js').then((Sentry) => {
|
|
222
|
+
Sentry.init({
|
|
223
|
+
dsn: 'https://xxxxxxxx@sentry.io/12345',
|
|
224
|
+
// ...其他配置
|
|
225
|
+
});
|
|
226
|
+
console.log('Sentry 异步加载并初始化成功');
|
|
227
|
+
}).catch(err => {
|
|
228
|
+
console.error('Sentry 加载失败', err);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
*通过这种方式,Sentry 的 200KB 体积将**全部算入 `subpackageA` 的分包体积**,主包占用为 0!*
|
|
235
|
+
|
|
236
|
+
### 方案 B:其他小程序平台(字节、百度等)
|
|
237
|
+
|
|
238
|
+
对于暂不支持 `require.async` 的平台,您可以采用**分包预下载 + API 动态加载**的方式:
|
|
239
|
+
|
|
240
|
+
1. 同样将 SDK 放入分包(如 `subpackageA`)。
|
|
241
|
+
2. 在 `app.js` 中使用平台原生的分包加载 API 先下载分包,下载成功后再通过同步 `require` 引入 SDK:
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
// 以字节小程序为例
|
|
245
|
+
App({
|
|
246
|
+
onLaunch() {
|
|
247
|
+
const loadTask = tt.loadSubpackage({
|
|
248
|
+
name: 'subpackageA',
|
|
249
|
+
success: () => {
|
|
250
|
+
// 分包加载成功后,就可以安全地 require 了
|
|
251
|
+
const Sentry = require('./subpackageA/sentry-miniapp.js');
|
|
252
|
+
Sentry.init({ dsn: '...' });
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
*注:如果您使用的是 Taro / uni-app 等跨端框架,可以直接使用 `import('sentry-miniapp')` 动态导入语法,框架会在编译时自动抹平各端差异。*
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
150
263
|
## ❓ 常见问题 (FAQ)
|
|
151
264
|
|
|
152
265
|
### 1. 初始化后无法自动上报异常,必须在 `onError` 中手动调 API 吗?
|
|
@@ -4938,7 +4938,7 @@ function addBreadcrumb(breadcrumb, hint) {
|
|
|
4938
4938
|
}
|
|
4939
4939
|
isolationScope.addBreadcrumb(finalBreadcrumb, maxBreadcrumbs);
|
|
4940
4940
|
}
|
|
4941
|
-
const SDK_VERSION = "1.
|
|
4941
|
+
const SDK_VERSION = "1.3.1";
|
|
4942
4942
|
const SDK_NAME = "sentry.javascript.miniapp";
|
|
4943
4943
|
const getSDK = () => {
|
|
4944
4944
|
let currentSdk = {
|
|
@@ -5140,15 +5140,16 @@ function createMiniappTransport(options) {
|
|
|
5140
5140
|
}
|
|
5141
5141
|
return createTransport(options, makeRequest);
|
|
5142
5142
|
}
|
|
5143
|
-
const
|
|
5143
|
+
const DEFAULT_OFFLINE_CACHE_SIZE = 30;
|
|
5144
5144
|
const OFFLINE_STORE_KEY = "sentry_offline_store";
|
|
5145
|
-
function createMiniappOfflineStore(
|
|
5145
|
+
function createMiniappOfflineStore(options) {
|
|
5146
|
+
const maxCacheSize = options.offlineCacheLimit || DEFAULT_OFFLINE_CACHE_SIZE;
|
|
5146
5147
|
return {
|
|
5147
5148
|
push: (env) => __async(null, null, function* () {
|
|
5148
5149
|
try {
|
|
5149
5150
|
const store = getStore();
|
|
5150
5151
|
store.push(env);
|
|
5151
|
-
if (store.length >
|
|
5152
|
+
if (store.length > maxCacheSize) {
|
|
5152
5153
|
store.shift();
|
|
5153
5154
|
}
|
|
5154
5155
|
setStore(store);
|
|
@@ -5160,7 +5161,7 @@ function createMiniappOfflineStore(_options) {
|
|
|
5160
5161
|
try {
|
|
5161
5162
|
const store = getStore();
|
|
5162
5163
|
store.unshift(env);
|
|
5163
|
-
if (store.length >
|
|
5164
|
+
if (store.length > maxCacheSize) {
|
|
5164
5165
|
store.pop();
|
|
5165
5166
|
}
|
|
5166
5167
|
setStore(store);
|
|
@@ -5225,6 +5226,7 @@ class MiniappClient extends Client {
|
|
|
5225
5226
|
}));
|
|
5226
5227
|
if (options.enableOfflineCache !== false) {
|
|
5227
5228
|
return makeOfflineTransport(() => baseTransport)(__spreadProps(__spreadValues({}, transportOptions), {
|
|
5229
|
+
offlineCacheLimit: options.offlineCacheLimit,
|
|
5228
5230
|
createStore: createMiniappOfflineStore,
|
|
5229
5231
|
flushAtStartup: true
|
|
5230
5232
|
// 启动时自动重试发送
|
|
@@ -5319,29 +5321,14 @@ class MiniappClient extends Client {
|
|
|
5319
5321
|
}
|
|
5320
5322
|
}
|
|
5321
5323
|
/**
|
|
5322
|
-
*
|
|
5323
|
-
*
|
|
5324
|
-
*
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
if (showModal) {
|
|
5331
|
-
showModal({
|
|
5332
|
-
title: options.title || "错误反馈",
|
|
5333
|
-
content: options.subtitle || "应用遇到了一个错误,是否要发送错误报告?",
|
|
5334
|
-
confirmText: "发送",
|
|
5335
|
-
cancelText: "取消",
|
|
5336
|
-
success: (res) => {
|
|
5337
|
-
if (res.confirm && options.onLoad) {
|
|
5338
|
-
options.onLoad();
|
|
5339
|
-
}
|
|
5340
|
-
}
|
|
5341
|
-
});
|
|
5342
|
-
} else {
|
|
5343
|
-
console.warn("sentry-miniapp: showModal is not available in current miniapp platform", options);
|
|
5344
|
-
}
|
|
5324
|
+
* @deprecated Miniapp environment does not support Sentry's default HTML report dialog.
|
|
5325
|
+
* Please implement your own UI form to collect user feedback (name, email, comments)
|
|
5326
|
+
* and use `Sentry.captureFeedback()` to submit it to Sentry.
|
|
5327
|
+
*/
|
|
5328
|
+
showReportDialog(_options = {}) {
|
|
5329
|
+
console.warn(
|
|
5330
|
+
"[sentry-miniapp] showReportDialog is deprecated and does nothing. Please build your own UI and use `Sentry.captureFeedback()` instead."
|
|
5331
|
+
);
|
|
5345
5332
|
}
|
|
5346
5333
|
/**
|
|
5347
5334
|
* Capture feedback using the new feedback API.
|
|
@@ -5555,13 +5542,13 @@ const _TryCatch = class _TryCatch {
|
|
|
5555
5542
|
setupOnce() {
|
|
5556
5543
|
const global2 = globalThis;
|
|
5557
5544
|
if (global2.setTimeout) {
|
|
5558
|
-
fill(global2, "setTimeout", this._wrapTimeFunction.bind(this));
|
|
5545
|
+
fill$1(global2, "setTimeout", this._wrapTimeFunction.bind(this));
|
|
5559
5546
|
}
|
|
5560
5547
|
if (global2.setInterval) {
|
|
5561
|
-
fill(global2, "setInterval", this._wrapTimeFunction.bind(this));
|
|
5548
|
+
fill$1(global2, "setInterval", this._wrapTimeFunction.bind(this));
|
|
5562
5549
|
}
|
|
5563
5550
|
if (global2.requestAnimationFrame) {
|
|
5564
|
-
fill(global2, "requestAnimationFrame", this._wrapRAF.bind(this));
|
|
5551
|
+
fill$1(global2, "requestAnimationFrame", this._wrapRAF.bind(this));
|
|
5565
5552
|
}
|
|
5566
5553
|
}
|
|
5567
5554
|
};
|
|
@@ -5642,7 +5629,7 @@ function wrap$1(fn, options = {}, before) {
|
|
|
5642
5629
|
}
|
|
5643
5630
|
return sentryWrapped;
|
|
5644
5631
|
}
|
|
5645
|
-
function fill(source, name, replacementFactory) {
|
|
5632
|
+
function fill$1(source, name, replacementFactory) {
|
|
5646
5633
|
if (!(name in source)) {
|
|
5647
5634
|
return;
|
|
5648
5635
|
}
|
|
@@ -6665,13 +6652,173 @@ let PerformanceIntegration = _PerformanceIntegration;
|
|
|
6665
6652
|
const performanceIntegration = (options) => {
|
|
6666
6653
|
return () => new PerformanceIntegration(options);
|
|
6667
6654
|
};
|
|
6655
|
+
const _RewriteFrames = class _RewriteFrames {
|
|
6656
|
+
constructor(options = {}) {
|
|
6657
|
+
this.name = _RewriteFrames.id;
|
|
6658
|
+
this._prefix = options.prefix || "app:///";
|
|
6659
|
+
}
|
|
6660
|
+
/**
|
|
6661
|
+
* @inheritDoc
|
|
6662
|
+
*/
|
|
6663
|
+
setupOnce() {
|
|
6664
|
+
}
|
|
6665
|
+
/**
|
|
6666
|
+
* @inheritDoc
|
|
6667
|
+
*/
|
|
6668
|
+
processEvent(event) {
|
|
6669
|
+
if (event.exception && event.exception.values) {
|
|
6670
|
+
event.exception.values.forEach((exception) => {
|
|
6671
|
+
if (exception.stacktrace && exception.stacktrace.frames) {
|
|
6672
|
+
exception.stacktrace.frames.forEach((frame) => {
|
|
6673
|
+
if (frame.filename) {
|
|
6674
|
+
frame.filename = this._normalizeFilename(frame.filename);
|
|
6675
|
+
}
|
|
6676
|
+
});
|
|
6677
|
+
}
|
|
6678
|
+
});
|
|
6679
|
+
}
|
|
6680
|
+
return event;
|
|
6681
|
+
}
|
|
6682
|
+
/**
|
|
6683
|
+
* Normalizes a filename from various miniapp platforms
|
|
6684
|
+
*/
|
|
6685
|
+
_normalizeFilename(filename) {
|
|
6686
|
+
let normalized = filename;
|
|
6687
|
+
normalized = normalized.replace(/^(appservice|app-service|WAService)\//i, "").replace(/^https?:\/\/[^/]+\//i, "").replace(/^[a-z]+:\/\//i, "").replace(/^\//, "");
|
|
6688
|
+
if (normalized.startsWith(this._prefix)) {
|
|
6689
|
+
return normalized;
|
|
6690
|
+
}
|
|
6691
|
+
return `${this._prefix}${normalized}`;
|
|
6692
|
+
}
|
|
6693
|
+
};
|
|
6694
|
+
_RewriteFrames.id = "RewriteFrames";
|
|
6695
|
+
let RewriteFrames = _RewriteFrames;
|
|
6696
|
+
function fill(source, name, replacementFactory) {
|
|
6697
|
+
if (!(name in source)) {
|
|
6698
|
+
return;
|
|
6699
|
+
}
|
|
6700
|
+
const original = source[name];
|
|
6701
|
+
const wrapped = replacementFactory(original);
|
|
6702
|
+
if (typeof wrapped === "function") {
|
|
6703
|
+
try {
|
|
6704
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
6705
|
+
wrapped.prototype.constructor = wrapped;
|
|
6706
|
+
} catch (_Oo) {
|
|
6707
|
+
}
|
|
6708
|
+
}
|
|
6709
|
+
source[name] = wrapped;
|
|
6710
|
+
}
|
|
6711
|
+
const _NetworkBreadcrumbs = class _NetworkBreadcrumbs {
|
|
6712
|
+
constructor(options = {}) {
|
|
6713
|
+
this.name = _NetworkBreadcrumbs.id;
|
|
6714
|
+
this._traceNetworkBody = !!options.traceNetworkBody;
|
|
6715
|
+
}
|
|
6716
|
+
/**
|
|
6717
|
+
* @inheritDoc
|
|
6718
|
+
*/
|
|
6719
|
+
setupOnce() {
|
|
6720
|
+
const miniappSdk = sdk();
|
|
6721
|
+
if (miniappSdk && typeof miniappSdk.request === "function") {
|
|
6722
|
+
fill(miniappSdk, "request", this._createRequestWrapper.bind(this));
|
|
6723
|
+
}
|
|
6724
|
+
if (miniappSdk && typeof miniappSdk.httpRequest === "function") {
|
|
6725
|
+
fill(miniappSdk, "httpRequest", this._createRequestWrapper.bind(this));
|
|
6726
|
+
}
|
|
6727
|
+
}
|
|
6728
|
+
/**
|
|
6729
|
+
* Wraps the miniapp request API to capture breadcrumbs
|
|
6730
|
+
*/
|
|
6731
|
+
_createRequestWrapper(originalRequest) {
|
|
6732
|
+
const traceNetworkBody = this._traceNetworkBody;
|
|
6733
|
+
return function(options) {
|
|
6734
|
+
if (!options || typeof options !== "object") {
|
|
6735
|
+
return originalRequest.call(this, options);
|
|
6736
|
+
}
|
|
6737
|
+
const url = options.url || "";
|
|
6738
|
+
const client = getClient();
|
|
6739
|
+
let dsnUrl = "";
|
|
6740
|
+
if (client) {
|
|
6741
|
+
const dsn = client.getOptions().dsn;
|
|
6742
|
+
if (dsn) {
|
|
6743
|
+
try {
|
|
6744
|
+
const dsnMatch = dsn.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?([^:/\n]+)/i);
|
|
6745
|
+
if (dsnMatch && dsnMatch[1]) {
|
|
6746
|
+
dsnUrl = dsnMatch[1];
|
|
6747
|
+
}
|
|
6748
|
+
} catch (e) {
|
|
6749
|
+
}
|
|
6750
|
+
}
|
|
6751
|
+
}
|
|
6752
|
+
if (typeof url === "string") {
|
|
6753
|
+
const isSentryRequest = dsnUrl && url.indexOf(dsnUrl) !== -1 || url.indexOf("sentry.io") !== -1;
|
|
6754
|
+
if (isSentryRequest) {
|
|
6755
|
+
return originalRequest.call(this, options);
|
|
6756
|
+
}
|
|
6757
|
+
}
|
|
6758
|
+
const method = (options.method || "GET").toUpperCase();
|
|
6759
|
+
const requestData = options.data;
|
|
6760
|
+
const breadcrumbData = {
|
|
6761
|
+
url,
|
|
6762
|
+
method
|
|
6763
|
+
};
|
|
6764
|
+
if (traceNetworkBody && requestData) {
|
|
6765
|
+
try {
|
|
6766
|
+
breadcrumbData["request_body"] = typeof requestData === "string" ? requestData : JSON.stringify(requestData);
|
|
6767
|
+
} catch (e) {
|
|
6768
|
+
breadcrumbData["request_body"] = "[Cannot serialize request body]";
|
|
6769
|
+
}
|
|
6770
|
+
}
|
|
6771
|
+
const originalSuccess = options.success;
|
|
6772
|
+
const originalFail = options.fail;
|
|
6773
|
+
options.success = function(...args) {
|
|
6774
|
+
const res = args[0] || {};
|
|
6775
|
+
const statusCode = res.statusCode || res.status;
|
|
6776
|
+
breadcrumbData["status_code"] = statusCode;
|
|
6777
|
+
if (traceNetworkBody && res.data) {
|
|
6778
|
+
try {
|
|
6779
|
+
breadcrumbData["response_body"] = typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
6780
|
+
} catch (e) {
|
|
6781
|
+
breadcrumbData["response_body"] = "[Cannot serialize response body]";
|
|
6782
|
+
}
|
|
6783
|
+
}
|
|
6784
|
+
addBreadcrumb({
|
|
6785
|
+
type: "http",
|
|
6786
|
+
category: "xhr",
|
|
6787
|
+
data: breadcrumbData,
|
|
6788
|
+
level: statusCode >= 400 ? "warning" : "info"
|
|
6789
|
+
});
|
|
6790
|
+
if (typeof originalSuccess === "function") {
|
|
6791
|
+
return originalSuccess.apply(this, args);
|
|
6792
|
+
}
|
|
6793
|
+
};
|
|
6794
|
+
options.fail = function(...args) {
|
|
6795
|
+
const err = args[0] || {};
|
|
6796
|
+
breadcrumbData["error"] = err.errMsg || err.errorMessage || "Network request failed";
|
|
6797
|
+
addBreadcrumb({
|
|
6798
|
+
type: "http",
|
|
6799
|
+
category: "xhr",
|
|
6800
|
+
data: breadcrumbData,
|
|
6801
|
+
level: "error"
|
|
6802
|
+
});
|
|
6803
|
+
if (typeof originalFail === "function") {
|
|
6804
|
+
return originalFail.apply(this, args);
|
|
6805
|
+
}
|
|
6806
|
+
};
|
|
6807
|
+
return originalRequest.call(this, options);
|
|
6808
|
+
};
|
|
6809
|
+
}
|
|
6810
|
+
};
|
|
6811
|
+
_NetworkBreadcrumbs.id = "NetworkBreadcrumbs";
|
|
6812
|
+
let NetworkBreadcrumbs = _NetworkBreadcrumbs;
|
|
6668
6813
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
6669
6814
|
__proto__: null,
|
|
6670
6815
|
Dedupe,
|
|
6671
6816
|
GlobalHandlers,
|
|
6672
6817
|
HttpContext,
|
|
6673
6818
|
LinkedErrors,
|
|
6819
|
+
NetworkBreadcrumbs,
|
|
6674
6820
|
PerformanceIntegration,
|
|
6821
|
+
RewriteFrames,
|
|
6675
6822
|
Router,
|
|
6676
6823
|
System,
|
|
6677
6824
|
TryCatch,
|
|
@@ -6707,6 +6854,10 @@ function init(options = {}) {
|
|
|
6707
6854
|
stackParser: () => [],
|
|
6708
6855
|
transport: options.transport
|
|
6709
6856
|
});
|
|
6857
|
+
if (opts.enableSourceMap !== false) {
|
|
6858
|
+
opts.integrations.push(new RewriteFrames());
|
|
6859
|
+
}
|
|
6860
|
+
opts.integrations.push(new NetworkBreadcrumbs({ traceNetworkBody: opts.traceNetworkBody }));
|
|
6710
6861
|
setContext("miniapp", {
|
|
6711
6862
|
platform: appName,
|
|
6712
6863
|
environment: "miniapp"
|
|
@@ -6729,13 +6880,10 @@ function init(options = {}) {
|
|
|
6729
6880
|
initAndBind(MiniappClient, opts);
|
|
6730
6881
|
return getCurrentScope().getClient();
|
|
6731
6882
|
}
|
|
6732
|
-
function showReportDialog(
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
} else {
|
|
6737
|
-
console.warn("sentry-miniapp: No client available for showReportDialog");
|
|
6738
|
-
}
|
|
6883
|
+
function showReportDialog(_options = {}) {
|
|
6884
|
+
console.warn(
|
|
6885
|
+
"[sentry-miniapp] showReportDialog is deprecated and does nothing. Please build your own UI and use `Sentry.captureFeedback()` instead."
|
|
6886
|
+
);
|
|
6739
6887
|
}
|
|
6740
6888
|
function wrap(fn) {
|
|
6741
6889
|
return (function(...args) {
|