@luciq/react-native 18.0.0 β 18.2.0-14799-SNAPSHOT
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 +30 -0
- package/README.md +0 -2
- package/RNLuciq.podspec +2 -2
- package/android/build.gradle +1 -2
- package/android/native.gradle +1 -1
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqBugReportingModule.java +23 -1
- package/bin/config/migration-config.json +5 -5
- package/bin/index.js +2 -7
- package/cli/config/migration-config.json +5 -5
- package/cli/upload/migrate.ts +2 -8
- package/dangerfile.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/models/ProactiveReportingConfigs.d.ts +10 -0
- package/dist/models/ProactiveReportingConfigs.js +22 -0
- package/dist/modules/BugReporting.d.ts +6 -0
- package/dist/modules/BugReporting.js +7 -0
- package/dist/native/NativeBugReporting.d.ts +1 -0
- package/dist/native/NativeCrashReporting.d.ts +8 -0
- package/dist/utils/LuciqConstants.d.ts +2 -0
- package/dist/utils/LuciqConstants.js +2 -0
- package/dist/utils/LuciqUtils.js +17 -0
- package/dist/utils/XhrNetworkInterceptor.js +9 -4
- package/ios/RNLuciq/LuciqAPMBridge.h +0 -2
- package/ios/RNLuciq/LuciqBugReportingBridge.h +2 -0
- package/ios/RNLuciq/LuciqBugReportingBridge.m +8 -0
- package/ios/native.rb +1 -1
- package/package.json +1 -2
- package/src/index.ts +6 -0
- package/src/models/ProactiveReportingConfigs.ts +37 -0
- package/src/modules/BugReporting.ts +13 -1
- package/src/native/NativeBugReporting.ts +6 -0
- package/src/native/NativeCrashReporting.ts +8 -0
- package/src/utils/LuciqConstants.ts +4 -0
- package/src/utils/LuciqUtils.ts +18 -1
- package/src/utils/XhrNetworkInterceptor.ts +9 -5
- package/upload/index.js +2 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [18.2.0](https://github.com/luciqai/luciq-reactnative-sdk/compare/v18.2.0...18.0.1)
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Bump Instabug iOS SDK to v18.2.0 ([#11](https://github.com/luciqai/luciq-reactnative-sdk/pull/11)). [See release notes](https://github.com/luciqai/Luciq-iOS-sdk/releases/tag/18.2.0).
|
|
8
|
+
|
|
9
|
+
- Bump Instabug Android SDK to v19.1.0 ([#11](https://github.com/luciqai/luciq-reactnative-sdk/pull/11)). [See release notes](https://github.com/luciqai/Luciq-Android-sdk/releases/tag/v19.1.0).
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Replace jcenter with mavencentral. ([#10](https://github.com/luciqai/luciq-reactnative-sdk/pull/10))
|
|
14
|
+
|
|
15
|
+
## [18.0.1] (https://github.com/luciqai/luciq-reactnative-sdk/compare/v18.0.1...18.0.0) (October 27, 2025)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Add support for proactive bug-reporting ([#2](https://github.com/luciqai/luciq-reactnative-sdk/pull/2))
|
|
20
|
+
-
|
|
21
|
+
- Add support for chaining errors. ([#3](https://github.com/luciqai/luciq-reactnative-sdk/pull/3))
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Bump Instabug iOS SDK to v18.0.1 ([#6](https://github.com/luciqai/luciq-reactnative-sdk/pull/7)). [See release notes](https://github.com/luciqai/Luciq-iOS-sdk/releases/tag/18.0.1).
|
|
26
|
+
|
|
27
|
+
- Bump Instabug Android SDK to v18.0.1 ([#6](https://github.com/luciqai/luciq-reactnative-sdk/pull/7)). [See release notes](https://github.com/luciqai/Luciq-Android-sdk/releases/tag/v18.0.1).
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- guard GraphQL network parsing that caused a crash. ([#5](https://github.com/luciqai/luciq-reactnative-sdk/pull/5))
|
|
32
|
+
|
|
3
33
|
## [18.0.0](https://github.com/luciqai/luciq-reactnative-sdk/compare/v18.0.0...dev) (September 24, 2025)
|
|
4
34
|
|
|
5
35
|
- SDK rebranded from Instabug to Luciq.
|
package/README.md
CHANGED
|
@@ -63,8 +63,6 @@ Luciq.init({
|
|
|
63
63
|
|
|
64
64
|
_You can find your app token by selecting the SDK tab from your [**Luciq dashboard**](https://dashboard.luciq.ai)._
|
|
65
65
|
|
|
66
|
-
> :warning: If you're updating the SDK from versions prior to v11, please check our [migration guide](https://docs.luciq.ai/docs/react-native-migration-guide).
|
|
67
|
-
|
|
68
66
|
## Microphone and Photo Library Usage Description (iOS Only)
|
|
69
67
|
|
|
70
68
|
Luciq needs access to the microphone and photo library to be able to let users add audio and video attachments. Starting from iOS 10, apps that donβt provide a usage description for those 2 permissions would be rejected when submitted to the App Store.
|
package/RNLuciq.podspec
CHANGED
package/android/build.gradle
CHANGED
package/android/native.gradle
CHANGED
|
@@ -23,8 +23,9 @@ import ai.luciq.reactlibrary.utils.ArrayUtil;
|
|
|
23
23
|
import ai.luciq.reactlibrary.utils.EventEmitterModule;
|
|
24
24
|
import ai.luciq.reactlibrary.utils.MainThreadHandler;
|
|
25
25
|
import ai.luciq.bug.userConsent.ActionType;
|
|
26
|
-
|
|
27
26
|
import java.util.ArrayList;
|
|
27
|
+
import ai.luciq.bug.ProactiveReportingConfigs;
|
|
28
|
+
|
|
28
29
|
|
|
29
30
|
import javax.annotation.Nonnull;
|
|
30
31
|
|
|
@@ -439,6 +440,27 @@ public class RNLuciqBugReportingModule extends EventEmitterModule {
|
|
|
439
440
|
});
|
|
440
441
|
|
|
441
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* prompts end users to submit their feedback after our SDK automatically detects a frustrating experience.
|
|
445
|
+
*
|
|
446
|
+
* @param enabled controls the state of the feature
|
|
447
|
+
* @param modalDelayAfterDetection controls the time gap between detecting a frustrating experience
|
|
448
|
+
* @param gapBetweenModals controls the time gap between showing 2 proactive reporting dialogs in seconds
|
|
449
|
+
*/
|
|
450
|
+
@ReactMethod
|
|
451
|
+
public void setProactiveReportingConfigurations(final boolean enabled, final int gapBetweenModals, final int modalDelayAfterDetection) {
|
|
452
|
+
MainThreadHandler.runOnMainThread(new Runnable() {
|
|
453
|
+
@Override
|
|
454
|
+
public void run() {
|
|
455
|
+
ProactiveReportingConfigs configs = new ProactiveReportingConfigs.Builder()
|
|
456
|
+
.setGapBetweenModals(gapBetweenModals) // Time in seconds
|
|
457
|
+
.setModalDelayAfterDetection(modalDelayAfterDetection) // Time in seconds
|
|
458
|
+
.isEnabled(enabled) //Enable/disable
|
|
459
|
+
.build();
|
|
460
|
+
BugReporting.setProactiveReportingConfigurations(configs);
|
|
442
461
|
|
|
443
462
|
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
444
466
|
}
|
|
@@ -7,27 +7,27 @@
|
|
|
7
7
|
"searchReplace": [
|
|
8
8
|
{
|
|
9
9
|
"search": "com\\.instabug\\.library:instabug:[0-9]+\\.[0-9]+\\.[0-9]+",
|
|
10
|
-
"replacement": "ai.luciq.library:luciq:18.
|
|
10
|
+
"replacement": "ai.luciq.library:luciq:18.2.0",
|
|
11
11
|
"isRegex": true
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"search": "com\\.instabug\\.library:instabug:[0-9]+\\.[0-9]+\\.[0-9]+-.*",
|
|
15
|
-
"replacement": "ai.luciq.library:luciq:18.
|
|
15
|
+
"replacement": "ai.luciq.library:luciq:18.2.0",
|
|
16
16
|
"isRegex": true
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"search": "com\\.instabug\\.library:instabug:[0-9]+\\.[0-9]+\\.[0-9]+-SNAPSHOT",
|
|
20
|
-
"replacement": "ai.luciq.library:luciq:18.
|
|
20
|
+
"replacement": "ai.luciq.library:luciq:18.2.0",
|
|
21
21
|
"isRegex": true
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"search": "\"instabug-react-native\":\\s*\"[^\"]+\"",
|
|
25
|
-
"replacement": "\"@luciq/react-native\": \"^18.
|
|
25
|
+
"replacement": "\"@luciq/react-native\": \"^18.2.0\"",
|
|
26
26
|
"isRegex": true
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"search": "'instabug-react-native':\\s*'[^']+'",
|
|
30
|
-
"replacement": "'@luciq/react-native': '^18.
|
|
30
|
+
"replacement": "'@luciq/react-native': '^18.2.0'",
|
|
31
31
|
"isRegex": true
|
|
32
32
|
}
|
|
33
33
|
],
|
package/bin/index.js
CHANGED
|
@@ -18975,8 +18975,6 @@ const migrate = async (opts) => {
|
|
|
18975
18975
|
// Sort methods by priority (lower number = higher priority)
|
|
18976
18976
|
const sortedMethods = enabledMethods.sort((a, b) => (a.priority || 999) - (b.priority || 999));
|
|
18977
18977
|
if (!opts.silent) {
|
|
18978
|
-
console.log('π Starting migration with all enabled methods');
|
|
18979
|
-
console.log(`π Found ${sortedMethods.length} enabled method(s):`);
|
|
18980
18978
|
sortedMethods.forEach((method) => {
|
|
18981
18979
|
console.log(` - ${method.name}: ${method.description}`);
|
|
18982
18980
|
});
|
|
@@ -19076,13 +19074,13 @@ function processFile(filePath, method, dryRun, silent) {
|
|
|
19076
19074
|
if (newContent !== content) {
|
|
19077
19075
|
if (dryRun) {
|
|
19078
19076
|
if (!silent) {
|
|
19079
|
-
console.log(`π
|
|
19077
|
+
console.log(`π Update content: ${filePath}`);
|
|
19080
19078
|
}
|
|
19081
19079
|
return;
|
|
19082
19080
|
}
|
|
19083
19081
|
fs$2.writeFileSync(filePath, newContent, 'utf8');
|
|
19084
19082
|
if (!silent) {
|
|
19085
|
-
console.log(`π
|
|
19083
|
+
console.log(`π Update content: ${filePath}`);
|
|
19086
19084
|
}
|
|
19087
19085
|
}
|
|
19088
19086
|
}
|
|
@@ -19121,9 +19119,6 @@ async function executeAllMethods(methods, dryRun, silent) {
|
|
|
19121
19119
|
}
|
|
19122
19120
|
async function executeMethod(method, dryRun, silent) {
|
|
19123
19121
|
const startDir = process.cwd();
|
|
19124
|
-
if (!silent) {
|
|
19125
|
-
console.log(`π Executing method: ${method.name}`);
|
|
19126
|
-
}
|
|
19127
19122
|
walkDirectory(startDir, method, dryRun, silent);
|
|
19128
19123
|
}
|
|
19129
19124
|
|
|
@@ -7,27 +7,27 @@
|
|
|
7
7
|
"searchReplace": [
|
|
8
8
|
{
|
|
9
9
|
"search": "com\\.instabug\\.library:instabug:[0-9]+\\.[0-9]+\\.[0-9]+",
|
|
10
|
-
"replacement": "ai.luciq.library:luciq:18.
|
|
10
|
+
"replacement": "ai.luciq.library:luciq:18.2.0",
|
|
11
11
|
"isRegex": true
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"search": "com\\.instabug\\.library:instabug:[0-9]+\\.[0-9]+\\.[0-9]+-.*",
|
|
15
|
-
"replacement": "ai.luciq.library:luciq:18.
|
|
15
|
+
"replacement": "ai.luciq.library:luciq:18.2.0",
|
|
16
16
|
"isRegex": true
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"search": "com\\.instabug\\.library:instabug:[0-9]+\\.[0-9]+\\.[0-9]+-SNAPSHOT",
|
|
20
|
-
"replacement": "ai.luciq.library:luciq:18.
|
|
20
|
+
"replacement": "ai.luciq.library:luciq:18.2.0",
|
|
21
21
|
"isRegex": true
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"search": "\"instabug-react-native\":\\s*\"[^\"]+\"",
|
|
25
|
-
"replacement": "\"@luciq/react-native\": \"^18.
|
|
25
|
+
"replacement": "\"@luciq/react-native\": \"^18.2.0\"",
|
|
26
26
|
"isRegex": true
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"search": "'instabug-react-native':\\s*'[^']+'",
|
|
30
|
-
"replacement": "'@luciq/react-native': '^18.
|
|
30
|
+
"replacement": "'@luciq/react-native': '^18.2.0'",
|
|
31
31
|
"isRegex": true
|
|
32
32
|
}
|
|
33
33
|
],
|
package/cli/upload/migrate.ts
CHANGED
|
@@ -80,8 +80,6 @@ export const migrate = async (opts: MigrateOptions): Promise<boolean> => {
|
|
|
80
80
|
const sortedMethods = enabledMethods.sort((a, b) => (a.priority || 999) - (b.priority || 999));
|
|
81
81
|
|
|
82
82
|
if (!opts.silent) {
|
|
83
|
-
console.log('π Starting migration with all enabled methods');
|
|
84
|
-
console.log(`π Found ${sortedMethods.length} enabled method(s):`);
|
|
85
83
|
sortedMethods.forEach((method) => {
|
|
86
84
|
console.log(` - ${method.name}: ${method.description}`);
|
|
87
85
|
});
|
|
@@ -201,14 +199,14 @@ function processFile(
|
|
|
201
199
|
if (newContent !== content) {
|
|
202
200
|
if (dryRun) {
|
|
203
201
|
if (!silent) {
|
|
204
|
-
console.log(`π
|
|
202
|
+
console.log(`π Update content: ${filePath}`);
|
|
205
203
|
}
|
|
206
204
|
return;
|
|
207
205
|
}
|
|
208
206
|
|
|
209
207
|
fs.writeFileSync(filePath, newContent, 'utf8');
|
|
210
208
|
if (!silent) {
|
|
211
|
-
console.log(`π
|
|
209
|
+
console.log(`π Update content: ${filePath}`);
|
|
212
210
|
}
|
|
213
211
|
}
|
|
214
212
|
} catch (error) {
|
|
@@ -263,9 +261,5 @@ async function executeMethod(
|
|
|
263
261
|
): Promise<void> {
|
|
264
262
|
const startDir = process.cwd();
|
|
265
263
|
|
|
266
|
-
if (!silent) {
|
|
267
|
-
console.log(`π Executing method: ${method.name}`);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
264
|
walkDirectory(startDir, method, dryRun, silent);
|
|
271
265
|
}
|
package/dangerfile.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import collectCoverage, { ReportType } from '@
|
|
1
|
+
import collectCoverage, { ReportType } from '@instabug/danger-plugin-coverage';
|
|
2
2
|
import { danger, fail, schedule, warn } from 'danger';
|
|
3
3
|
|
|
4
4
|
const hasSourceChanges = danger.git.modified_files.some((file) => file.startsWith('src/'));
|
package/dist/index.d.ts
CHANGED
|
@@ -8,12 +8,13 @@ import * as FeatureRequests from './modules/FeatureRequests';
|
|
|
8
8
|
import * as Luciq from './modules/Luciq';
|
|
9
9
|
import * as NetworkLogger from './modules/NetworkLogger';
|
|
10
10
|
import type { NetworkData, NetworkDataObfuscationHandler } from './modules/NetworkLogger';
|
|
11
|
+
import { createProactiveReportingConfig, type ProactiveReportingConfigOptions } from './models/ProactiveReportingConfigs';
|
|
11
12
|
import * as Replies from './modules/Replies';
|
|
12
13
|
import type { Survey } from './modules/Surveys';
|
|
13
14
|
import * as Surveys from './modules/Surveys';
|
|
14
15
|
import * as SessionReplay from './modules/SessionReplay';
|
|
15
16
|
import type { SessionMetadata } from './models/SessionMetadata';
|
|
16
17
|
export * from './utils/Enums';
|
|
17
|
-
export { Report, APM, BugReporting, CrashReporting, FeatureRequests, NetworkLogger, SessionReplay, Replies, Surveys, };
|
|
18
|
+
export { Report, APM, BugReporting, CrashReporting, FeatureRequests, NetworkLogger, SessionReplay, Replies, Surveys, ProactiveReportingConfigOptions, createProactiveReportingConfig, };
|
|
18
19
|
export type { LuciqConfig, Survey, NetworkData, NetworkDataObfuscationHandler, SessionMetadata, ThemeConfig, };
|
|
19
20
|
export default Luciq;
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,10 @@ import * as CrashReporting from './modules/CrashReporting';
|
|
|
6
6
|
import * as FeatureRequests from './modules/FeatureRequests';
|
|
7
7
|
import * as Luciq from './modules/Luciq';
|
|
8
8
|
import * as NetworkLogger from './modules/NetworkLogger';
|
|
9
|
+
import { createProactiveReportingConfig, } from './models/ProactiveReportingConfigs';
|
|
9
10
|
import * as Replies from './modules/Replies';
|
|
10
11
|
import * as Surveys from './modules/Surveys';
|
|
11
12
|
import * as SessionReplay from './modules/SessionReplay';
|
|
12
13
|
export * from './utils/Enums';
|
|
13
|
-
export { Report, APM, BugReporting, CrashReporting, FeatureRequests, NetworkLogger, SessionReplay, Replies, Surveys, };
|
|
14
|
+
export { Report, APM, BugReporting, CrashReporting, FeatureRequests, NetworkLogger, SessionReplay, Replies, Surveys, createProactiveReportingConfig, };
|
|
14
15
|
export default Luciq;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ProactiveReportingConfigOptions {
|
|
2
|
+
gapBetweenModals: number;
|
|
3
|
+
modalDelayAfterDetection: number;
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function createProactiveReportingConfig({ gapBetweenModals, modalDelayAfterDetection, enabled, }?: ProactiveReportingConfigOptions): {
|
|
7
|
+
gapBetweenModals: number;
|
|
8
|
+
modalDelayAfterDetection: number;
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Logger } from '../utils/logger';
|
|
2
|
+
import LuciqConstants from '../utils/LuciqConstants';
|
|
3
|
+
export function createProactiveReportingConfig({ gapBetweenModals = 24, modalDelayAfterDetection = 20, enabled = true, } = {
|
|
4
|
+
gapBetweenModals: 24,
|
|
5
|
+
modalDelayAfterDetection: 20,
|
|
6
|
+
enabled: true,
|
|
7
|
+
}) {
|
|
8
|
+
// Validation and defaults
|
|
9
|
+
if (gapBetweenModals <= 0) {
|
|
10
|
+
Logger.warn(LuciqConstants.GAP_MODEL_ERROR_MESSAGE);
|
|
11
|
+
gapBetweenModals = 24; // Use default value if invalid
|
|
12
|
+
}
|
|
13
|
+
if (modalDelayAfterDetection <= 0) {
|
|
14
|
+
Logger.warn(LuciqConstants.MODAL_DETECTION_ERROR_MESSAGE);
|
|
15
|
+
modalDelayAfterDetection = 20; // Use default value if invalid
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
gapBetweenModals,
|
|
19
|
+
modalDelayAfterDetection,
|
|
20
|
+
enabled,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProactiveReportingConfigOptions } from '../models/ProactiveReportingConfigs';
|
|
1
2
|
import type { DismissType, ExtendedBugReportMode, FloatingButtonPosition, InvocationEvent, InvocationOption, RecordingButtonPosition, ReportType, userConsentActionType } from '../utils/Enums';
|
|
2
3
|
/**
|
|
3
4
|
* Enables and disables manual invocation and prompt options for bug and feedback.
|
|
@@ -136,3 +137,8 @@ export declare const setDisclaimerText: (text: string) => void;
|
|
|
136
137
|
* @platform iOS
|
|
137
138
|
*/
|
|
138
139
|
export declare const setCommentMinimumCharacterCount: (limit: number, reportTypes?: ReportType[]) => void;
|
|
140
|
+
/**
|
|
141
|
+
** prompts end users to submit their feedback after our SDK automatically detects a frustrating experience.
|
|
142
|
+
* @param config configuration of proActive bug report.
|
|
143
|
+
*/
|
|
144
|
+
export declare const setProactiveReportingConfigurations: (config: ProactiveReportingConfigOptions) => void;
|
|
@@ -200,3 +200,10 @@ export const setCommentMinimumCharacterCount = (limit, reportTypes) => {
|
|
|
200
200
|
NativeBugReporting.setCommentMinimumCharacterCount(limit, reportTypes ?? []);
|
|
201
201
|
}
|
|
202
202
|
};
|
|
203
|
+
/**
|
|
204
|
+
** prompts end users to submit their feedback after our SDK automatically detects a frustrating experience.
|
|
205
|
+
* @param config configuration of proActive bug report.
|
|
206
|
+
*/
|
|
207
|
+
export const setProactiveReportingConfigurations = (config) => {
|
|
208
|
+
NativeBugReporting.setProactiveReportingConfigurations(config.enabled, config.gapBetweenModals, config.modalDelayAfterDetection);
|
|
209
|
+
};
|
|
@@ -22,6 +22,7 @@ export interface BugReportingNativeModule extends NativeModule {
|
|
|
22
22
|
setDidSelectPromptOptionHandler(handler: (promptOption: string) => void): void;
|
|
23
23
|
setOnSDKDismissedHandler(handler: (dismissType: DismissType, reportType: ReportType) => void): void;
|
|
24
24
|
addUserConsent(key: string, description: string, mandatory: boolean, checked: boolean, actionType?: userConsentActionType): void;
|
|
25
|
+
setProactiveReportingConfigurations(enabled: boolean, gapBetweenModals: number, modalDelayAfterDetection: number): void;
|
|
25
26
|
}
|
|
26
27
|
export declare const NativeBugReporting: BugReportingNativeModule;
|
|
27
28
|
export declare enum NativeEvents {
|
|
@@ -8,6 +8,14 @@ export interface CrashData {
|
|
|
8
8
|
os: (typeof Platform)['OS'];
|
|
9
9
|
platform: 'react_native';
|
|
10
10
|
exception: StackFrame[];
|
|
11
|
+
cause_crash?: CauseCrashData;
|
|
12
|
+
}
|
|
13
|
+
export interface CauseCrashData {
|
|
14
|
+
message: string;
|
|
15
|
+
e_message: string;
|
|
16
|
+
e_name: string;
|
|
17
|
+
exception: StackFrame[];
|
|
18
|
+
cause_crash?: CauseCrashData;
|
|
11
19
|
}
|
|
12
20
|
export interface CrashReportingNativeModule extends NativeModule {
|
|
13
21
|
setEnabled(isEnabled: boolean): void;
|
|
@@ -6,6 +6,8 @@ declare const LuciqConstants: {
|
|
|
6
6
|
SET_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE: string;
|
|
7
7
|
REMOVE_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE: string;
|
|
8
8
|
DEFAULT_METRO_PORT: string;
|
|
9
|
+
GAP_MODEL_ERROR_MESSAGE: string;
|
|
10
|
+
MODAL_DETECTION_ERROR_MESSAGE: string;
|
|
9
11
|
LCQ_APM_TAG: string;
|
|
10
12
|
SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE: string;
|
|
11
13
|
PLUGIN_NOT_INSTALLED_MESSAGE: string;
|
|
@@ -7,6 +7,8 @@ const LuciqConstants = {
|
|
|
7
7
|
SET_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE: 'LCQ-RN: Expected key and value passed to setUserAttribute to be of type string',
|
|
8
8
|
REMOVE_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE: 'LCQ-RN: Expected key and value passed to removeUserAttribute to be of type string',
|
|
9
9
|
DEFAULT_METRO_PORT: '8081',
|
|
10
|
+
GAP_MODEL_ERROR_MESSAGE: 'gapBetweenModals must be a positive number. Using default value of 24 seconds.',
|
|
11
|
+
MODAL_DETECTION_ERROR_MESSAGE: 'modalDelayAfterDetection must be a positive number. Using default value of 20 seconds.',
|
|
10
12
|
LCQ_APM_TAG: 'LCQ-APM: ',
|
|
11
13
|
SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE: 'Android Plugin Detected. Switched to Native Interception.',
|
|
12
14
|
PLUGIN_NOT_INSTALLED_MESSAGE: 'Network Spans will not be captured as Android Plugin is not installed. Disabling Native Interception to minimize data loss.',
|
package/dist/utils/LuciqUtils.js
CHANGED
|
@@ -32,6 +32,23 @@ export const getCrashDataFromError = (error) => {
|
|
|
32
32
|
platform: 'react_native',
|
|
33
33
|
exception: jsStackTrace,
|
|
34
34
|
};
|
|
35
|
+
// Recursively attach inner_crash objects (up to 3 levels)
|
|
36
|
+
let currentError = error;
|
|
37
|
+
let level = 0;
|
|
38
|
+
let parentCrash = jsonObject;
|
|
39
|
+
while (currentError.cause && level < 3) {
|
|
40
|
+
const cause = currentError.cause;
|
|
41
|
+
const innerCrash = {
|
|
42
|
+
message: `${cause.name} - ${cause.message}`,
|
|
43
|
+
e_message: cause.message,
|
|
44
|
+
e_name: cause.name,
|
|
45
|
+
exception: getStackTrace(cause),
|
|
46
|
+
};
|
|
47
|
+
parentCrash.cause_crash = innerCrash;
|
|
48
|
+
parentCrash = innerCrash;
|
|
49
|
+
currentError = cause;
|
|
50
|
+
level++;
|
|
51
|
+
}
|
|
35
52
|
return jsonObject;
|
|
36
53
|
};
|
|
37
54
|
export const getActiveRouteName = (navigationState) => {
|
|
@@ -199,11 +199,16 @@ export default {
|
|
|
199
199
|
cloneNetwork.gqlQueryName = '';
|
|
200
200
|
}
|
|
201
201
|
if (cloneNetwork.responseBody) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
try {
|
|
203
|
+
const responseObj = JSON.parse(cloneNetwork.responseBody);
|
|
204
|
+
if (responseObj.errors) {
|
|
205
|
+
cloneNetwork.serverErrorMessage = 'GraphQLError';
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
cloneNetwork.serverErrorMessage = '';
|
|
209
|
+
}
|
|
205
210
|
}
|
|
206
|
-
|
|
211
|
+
catch (_error) {
|
|
207
212
|
cloneNetwork.serverErrorMessage = '';
|
|
208
213
|
}
|
|
209
214
|
}
|
|
@@ -231,6 +231,14 @@ RCT_EXPORT_METHOD(addUserConsent:(NSString *)key
|
|
|
231
231
|
actionType:mappedActionType];
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
RCT_EXPORT_METHOD(setProactiveReportingConfigurations:(BOOL)enabled gap:(nonnull NSNumber* )gap model:(nonnull NSNumber* )modal) {
|
|
235
|
+
LCQProactiveReportingConfigurations *configurations = [[LCQProactiveReportingConfigurations alloc] init];
|
|
236
|
+
configurations.enabled = enabled; //Enable/disable
|
|
237
|
+
configurations.gapBetweenModals = gap; // Time in seconds
|
|
238
|
+
configurations.modalDelayAfterDetection = modal; // Time in seconds
|
|
239
|
+
[LCQBugReporting setProactiveReportingConfigurations:configurations];
|
|
240
|
+
}
|
|
241
|
+
|
|
234
242
|
|
|
235
243
|
@synthesize description;
|
|
236
244
|
|
package/ios/native.rb
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luciq/react-native",
|
|
3
3
|
"description": "Luciq is the Agentic Observability Platform built for Mobile.",
|
|
4
|
-
"version": "18.
|
|
4
|
+
"version": "18.2.0-14799-SNAPSHOT",
|
|
5
5
|
"author": "Luciq (https://luciq.ai)",
|
|
6
6
|
"repository": "github:luciqai/luciq-reactnative-sdk",
|
|
7
7
|
"homepage": "https://www.luciq.ai/platforms/react-native",
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@apollo/client": "^3.7.0",
|
|
46
|
-
"@instabug/danger-plugin-coverage": "Instabug/danger-plugin-coverage",
|
|
47
46
|
"@react-native-community/eslint-config": "^3.1.0",
|
|
48
47
|
"@react-navigation/native": "^6.1.7",
|
|
49
48
|
"@rollup/plugin-commonjs": "^25.0.3",
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,10 @@ import * as FeatureRequests from './modules/FeatureRequests';
|
|
|
10
10
|
import * as Luciq from './modules/Luciq';
|
|
11
11
|
import * as NetworkLogger from './modules/NetworkLogger';
|
|
12
12
|
import type { NetworkData, NetworkDataObfuscationHandler } from './modules/NetworkLogger';
|
|
13
|
+
import {
|
|
14
|
+
createProactiveReportingConfig,
|
|
15
|
+
type ProactiveReportingConfigOptions,
|
|
16
|
+
} from './models/ProactiveReportingConfigs';
|
|
13
17
|
import * as Replies from './modules/Replies';
|
|
14
18
|
import type { Survey } from './modules/Surveys';
|
|
15
19
|
import * as Surveys from './modules/Surveys';
|
|
@@ -27,6 +31,8 @@ export {
|
|
|
27
31
|
SessionReplay,
|
|
28
32
|
Replies,
|
|
29
33
|
Surveys,
|
|
34
|
+
ProactiveReportingConfigOptions,
|
|
35
|
+
createProactiveReportingConfig,
|
|
30
36
|
};
|
|
31
37
|
export type {
|
|
32
38
|
LuciqConfig,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Logger } from '../utils/logger';
|
|
2
|
+
import LuciqConstants from '../utils/LuciqConstants';
|
|
3
|
+
|
|
4
|
+
export interface ProactiveReportingConfigOptions {
|
|
5
|
+
gapBetweenModals: number;
|
|
6
|
+
modalDelayAfterDetection: number;
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createProactiveReportingConfig(
|
|
11
|
+
{
|
|
12
|
+
gapBetweenModals = 24,
|
|
13
|
+
modalDelayAfterDetection = 20,
|
|
14
|
+
enabled = true,
|
|
15
|
+
}: ProactiveReportingConfigOptions = {
|
|
16
|
+
gapBetweenModals: 24,
|
|
17
|
+
modalDelayAfterDetection: 20,
|
|
18
|
+
enabled: true,
|
|
19
|
+
},
|
|
20
|
+
) {
|
|
21
|
+
// Validation and defaults
|
|
22
|
+
if (gapBetweenModals <= 0) {
|
|
23
|
+
Logger.warn(LuciqConstants.GAP_MODEL_ERROR_MESSAGE);
|
|
24
|
+
gapBetweenModals = 24; // Use default value if invalid
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (modalDelayAfterDetection <= 0) {
|
|
28
|
+
Logger.warn(LuciqConstants.MODAL_DETECTION_ERROR_MESSAGE);
|
|
29
|
+
modalDelayAfterDetection = 20; // Use default value if invalid
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
gapBetweenModals,
|
|
34
|
+
modalDelayAfterDetection,
|
|
35
|
+
enabled,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import { NativeBugReporting, NativeEvents, emitter } from '../native/NativeBugReporting';
|
|
4
|
-
|
|
4
|
+
import type { ProactiveReportingConfigOptions } from '../models/ProactiveReportingConfigs';
|
|
5
5
|
import type {
|
|
6
6
|
DismissType,
|
|
7
7
|
ExtendedBugReportMode,
|
|
@@ -252,3 +252,15 @@ export const setCommentMinimumCharacterCount = (limit: number, reportTypes?: Rep
|
|
|
252
252
|
NativeBugReporting.setCommentMinimumCharacterCount(limit, reportTypes ?? []);
|
|
253
253
|
}
|
|
254
254
|
};
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
** prompts end users to submit their feedback after our SDK automatically detects a frustrating experience.
|
|
258
|
+
* @param config configuration of proActive bug report.
|
|
259
|
+
*/
|
|
260
|
+
export const setProactiveReportingConfigurations = (config: ProactiveReportingConfigOptions) => {
|
|
261
|
+
NativeBugReporting.setProactiveReportingConfigurations(
|
|
262
|
+
config.enabled,
|
|
263
|
+
config.gapBetweenModals,
|
|
264
|
+
config.modalDelayAfterDetection,
|
|
265
|
+
);
|
|
266
|
+
};
|
|
@@ -57,6 +57,12 @@ export interface BugReportingNativeModule extends NativeModule {
|
|
|
57
57
|
checked: boolean,
|
|
58
58
|
actionType?: userConsentActionType,
|
|
59
59
|
): void;
|
|
60
|
+
|
|
61
|
+
setProactiveReportingConfigurations(
|
|
62
|
+
enabled: boolean,
|
|
63
|
+
gapBetweenModals: number,
|
|
64
|
+
modalDelayAfterDetection: number,
|
|
65
|
+
): void;
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
export const NativeBugReporting = NativeModules.LCQBugReporting;
|
|
@@ -11,8 +11,16 @@ export interface CrashData {
|
|
|
11
11
|
os: (typeof Platform)['OS'];
|
|
12
12
|
platform: 'react_native';
|
|
13
13
|
exception: StackFrame[];
|
|
14
|
+
cause_crash?: CauseCrashData;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
export interface CauseCrashData {
|
|
18
|
+
message: string;
|
|
19
|
+
e_message: string;
|
|
20
|
+
e_name: string;
|
|
21
|
+
exception: StackFrame[];
|
|
22
|
+
cause_crash?: CauseCrashData;
|
|
23
|
+
}
|
|
16
24
|
export interface CrashReportingNativeModule extends NativeModule {
|
|
17
25
|
setEnabled(isEnabled: boolean): void;
|
|
18
26
|
sendJSCrash(data: CrashData | string): Promise<void>;
|
|
@@ -12,6 +12,10 @@ const LuciqConstants = {
|
|
|
12
12
|
REMOVE_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE:
|
|
13
13
|
'LCQ-RN: Expected key and value passed to removeUserAttribute to be of type string',
|
|
14
14
|
DEFAULT_METRO_PORT: '8081',
|
|
15
|
+
GAP_MODEL_ERROR_MESSAGE:
|
|
16
|
+
'gapBetweenModals must be a positive number. Using default value of 24 seconds.',
|
|
17
|
+
MODAL_DETECTION_ERROR_MESSAGE:
|
|
18
|
+
'modalDelayAfterDetection must be a positive number. Using default value of 20 seconds.',
|
|
15
19
|
LCQ_APM_TAG: 'LCQ-APM: ',
|
|
16
20
|
SWITCHED_TO_NATIVE_INTERCEPTION_MESSAGE:
|
|
17
21
|
'Android Plugin Detected. Switched to Native Interception.',
|
package/src/utils/LuciqUtils.ts
CHANGED
|
@@ -7,7 +7,7 @@ import parseErrorStackLib, {
|
|
|
7
7
|
import type { NavigationState as NavigationStateV5, PartialState } from '@react-navigation/native';
|
|
8
8
|
import type { NavigationState as NavigationStateV4 } from 'react-navigation';
|
|
9
9
|
|
|
10
|
-
import type { CrashData } from '../native/NativeCrashReporting';
|
|
10
|
+
import type { CauseCrashData, CrashData } from '../native/NativeCrashReporting';
|
|
11
11
|
import { NativeCrashReporting } from '../native/NativeCrashReporting';
|
|
12
12
|
import type { NetworkData } from './XhrNetworkInterceptor';
|
|
13
13
|
import { NativeLuciq } from '../native/NativeLuciq';
|
|
@@ -59,6 +59,23 @@ export const getCrashDataFromError = (error: Error) => {
|
|
|
59
59
|
platform: 'react_native',
|
|
60
60
|
exception: jsStackTrace,
|
|
61
61
|
};
|
|
62
|
+
// Recursively attach inner_crash objects (up to 3 levels)
|
|
63
|
+
let currentError: any = error;
|
|
64
|
+
let level = 0;
|
|
65
|
+
let parentCrash: CauseCrashData | CrashData = jsonObject;
|
|
66
|
+
while (currentError.cause && level < 3) {
|
|
67
|
+
const cause = currentError.cause as Error;
|
|
68
|
+
const innerCrash: CauseCrashData = {
|
|
69
|
+
message: `${cause.name} - ${cause.message}`,
|
|
70
|
+
e_message: cause.message,
|
|
71
|
+
e_name: cause.name,
|
|
72
|
+
exception: getStackTrace(cause),
|
|
73
|
+
};
|
|
74
|
+
parentCrash.cause_crash = innerCrash;
|
|
75
|
+
parentCrash = innerCrash;
|
|
76
|
+
currentError = cause;
|
|
77
|
+
level++;
|
|
78
|
+
}
|
|
62
79
|
return jsonObject;
|
|
63
80
|
};
|
|
64
81
|
|
|
@@ -275,11 +275,15 @@ export default {
|
|
|
275
275
|
cloneNetwork.gqlQueryName = '';
|
|
276
276
|
}
|
|
277
277
|
if (cloneNetwork.responseBody) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
278
|
+
try {
|
|
279
|
+
const responseObj = JSON.parse(cloneNetwork.responseBody);
|
|
280
|
+
|
|
281
|
+
if (responseObj.errors) {
|
|
282
|
+
cloneNetwork.serverErrorMessage = 'GraphQLError';
|
|
283
|
+
} else {
|
|
284
|
+
cloneNetwork.serverErrorMessage = '';
|
|
285
|
+
}
|
|
286
|
+
} catch (_error) {
|
|
283
287
|
cloneNetwork.serverErrorMessage = '';
|
|
284
288
|
}
|
|
285
289
|
}
|
package/upload/index.js
CHANGED
|
@@ -17155,8 +17155,6 @@ const migrate = async (opts) => {
|
|
|
17155
17155
|
// Sort methods by priority (lower number = higher priority)
|
|
17156
17156
|
const sortedMethods = enabledMethods.sort((a, b) => (a.priority || 999) - (b.priority || 999));
|
|
17157
17157
|
if (!opts.silent) {
|
|
17158
|
-
console.log('π Starting migration with all enabled methods');
|
|
17159
|
-
console.log(`π Found ${sortedMethods.length} enabled method(s):`);
|
|
17160
17158
|
sortedMethods.forEach((method) => {
|
|
17161
17159
|
console.log(` - ${method.name}: ${method.description}`);
|
|
17162
17160
|
});
|
|
@@ -17256,13 +17254,13 @@ function processFile(filePath, method, dryRun, silent) {
|
|
|
17256
17254
|
if (newContent !== content) {
|
|
17257
17255
|
if (dryRun) {
|
|
17258
17256
|
if (!silent) {
|
|
17259
|
-
console.log(`π
|
|
17257
|
+
console.log(`π Update content: ${filePath}`);
|
|
17260
17258
|
}
|
|
17261
17259
|
return;
|
|
17262
17260
|
}
|
|
17263
17261
|
fs$1.writeFileSync(filePath, newContent, 'utf8');
|
|
17264
17262
|
if (!silent) {
|
|
17265
|
-
console.log(`π
|
|
17263
|
+
console.log(`π Update content: ${filePath}`);
|
|
17266
17264
|
}
|
|
17267
17265
|
}
|
|
17268
17266
|
}
|
|
@@ -17301,9 +17299,6 @@ async function executeAllMethods(methods, dryRun, silent) {
|
|
|
17301
17299
|
}
|
|
17302
17300
|
async function executeMethod(method, dryRun, silent) {
|
|
17303
17301
|
const startDir = process.cwd();
|
|
17304
|
-
if (!silent) {
|
|
17305
|
-
console.log(`π Executing method: ${method.name}`);
|
|
17306
|
-
}
|
|
17307
17302
|
walkDirectory(startDir, method, dryRun, silent);
|
|
17308
17303
|
}
|
|
17309
17304
|
|