@luciq/react-native 19.4.0 → 19.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.
- package/.claude/agents/codebase-analyzer.md +33 -0
- package/.claude/agents/codebase-locator.md +42 -0
- package/.claude/agents/codebase-pattern-finder.md +40 -0
- package/.claude/commands/apply-pr-reviews.md +253 -0
- package/.claude/commands/create-jira-workitem.md +27 -0
- package/.claude/commands/create-pr.md +138 -0
- package/.claude/commands/create-public-release-notes.md +145 -0
- package/.claude/commands/create-rca.md +286 -0
- package/.claude/commands/debug-sdk.md +66 -0
- package/.claude/commands/describe-pr.md +40 -0
- package/.claude/commands/new-api.md +60 -0
- package/.claude/commands/new-feature.md +75 -0
- package/.claude/commands/pr-review.md +85 -0
- package/.claude/commands/research-codebase.md +41 -0
- package/.claude/commands/review.md +73 -0
- package/.claude/memory/MEMORY.md +1 -0
- package/.claude/memory/feedback_pr_title_format.md +10 -0
- package/.claude/rules/react-native-typescript.md +46 -0
- package/CHANGELOG.md +12 -0
- package/CLAUDE.md +125 -0
- package/android/native.gradle +1 -1
- package/android/src/main/java/ai/luciq/reactlibrary/LuciqScreenLoadingFrameTracker.java +88 -0
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqAPMModule.java +184 -10
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqReactnativeModule.java +5 -3
- package/dist/components/LuciqCaptureScreenLoading.d.ts +8 -0
- package/dist/components/LuciqCaptureScreenLoading.js +154 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/modules/APM.d.ts +19 -0
- package/dist/modules/APM.js +38 -0
- package/dist/modules/Luciq.d.ts +1 -1
- package/dist/modules/Luciq.js +169 -11
- package/dist/modules/apm/ScreenLoadingManager.d.ts +99 -0
- package/dist/modules/apm/ScreenLoadingManager.js +296 -0
- package/dist/native/NativeAPM.d.ts +9 -0
- package/dist/native/NativeLuciq.d.ts +1 -1
- package/dist/utils/LuciqUtils.d.ts +25 -0
- package/dist/utils/LuciqUtils.js +44 -0
- package/dist/utils/RouteMatcher.d.ts +30 -0
- package/dist/utils/RouteMatcher.js +67 -0
- package/ios/RNLuciq/LuciqAPMBridge.m +82 -0
- package/ios/RNLuciq/LuciqReactBridge.m +1 -1
- package/ios/RNLuciq/LuciqScreenLoadingFrameTracker.h +11 -0
- package/ios/RNLuciq/LuciqScreenLoadingFrameTracker.m +121 -0
- package/ios/RNLuciq/Util/LCQAPM+PrivateAPIs.h +14 -0
- package/ios/native.rb +1 -1
- package/package.json +4 -1
- package/scripts/get-github-app-token.sh +70 -0
- package/scripts/notify-github.sh +17 -8
- package/src/components/LuciqCaptureScreenLoading.tsx +210 -0
- package/src/index.ts +4 -0
- package/src/modules/APM.ts +42 -0
- package/src/modules/Luciq.ts +197 -11
- package/src/modules/apm/ScreenLoadingManager.ts +364 -0
- package/src/native/NativeAPM.ts +22 -0
- package/src/native/NativeLuciq.ts +1 -1
- package/src/utils/LuciqUtils.ts +49 -0
- package/src/utils/RouteMatcher.ts +83 -0
package/src/utils/LuciqUtils.ts
CHANGED
|
@@ -420,6 +420,54 @@ export function updateNetworkLogSnapshot(networkSnapshot: NetworkData) {
|
|
|
420
420
|
);
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
/**
|
|
424
|
+
* @internal
|
|
425
|
+
* This method is for internal use only.
|
|
426
|
+
*
|
|
427
|
+
* Parses a string value to an integer, returning null if the value is null or cannot be parsed.
|
|
428
|
+
* @param value The string value to parse
|
|
429
|
+
* @returns The parsed integer or null
|
|
430
|
+
*/
|
|
431
|
+
export function getIntValue(value: string | null): number | null {
|
|
432
|
+
if (value === null) {
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
const parsed = parseInt(value, 10);
|
|
436
|
+
return isNaN(parsed) ? null : parsed;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// One-time anchor captured at module load to convert performance.now() to epoch time.
|
|
440
|
+
// performance.now() gives high-resolution monotonic time (sub-ms precision) but relative
|
|
441
|
+
// to app start. We pair it with Date.now() once, then derive epoch from the offset.
|
|
442
|
+
const perfAnchorMs: number = performance.now();
|
|
443
|
+
const epochAnchorUs: number = Date.now() * 1000;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Returns a high-resolution monotonic timestamp in microseconds.
|
|
447
|
+
* Use this for all internal duration measurements.
|
|
448
|
+
*/
|
|
449
|
+
export function nowMicros(): number {
|
|
450
|
+
return performance.now() * 1000;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Converts an internal monotonic microsecond timestamp to epoch microseconds.
|
|
455
|
+
* Use this only when reporting to the native layer or external systems.
|
|
456
|
+
*/
|
|
457
|
+
export function toEpochMicros(monotonicUs: number): number {
|
|
458
|
+
const offsetUs = monotonicUs - perfAnchorMs * 1000;
|
|
459
|
+
return epochAnchorUs + offsetUs;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Converts an epoch microsecond timestamp to internal monotonic microseconds.
|
|
464
|
+
* Use this when receiving timestamps from the native layer that are epoch-based.
|
|
465
|
+
*/
|
|
466
|
+
export function fromEpochMicros(epochUs: number): number {
|
|
467
|
+
const offsetUs = epochUs - epochAnchorUs;
|
|
468
|
+
return perfAnchorMs * 1000 + offsetUs;
|
|
469
|
+
}
|
|
470
|
+
|
|
423
471
|
export default {
|
|
424
472
|
parseErrorStack,
|
|
425
473
|
captureJsErrors,
|
|
@@ -427,6 +475,7 @@ export default {
|
|
|
427
475
|
getFullRoute,
|
|
428
476
|
getStackTrace,
|
|
429
477
|
stringifyIfNotString,
|
|
478
|
+
getIntValue,
|
|
430
479
|
sendCrashReport,
|
|
431
480
|
reportNetworkLog,
|
|
432
481
|
generateTracePartialId,
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// TODO: This class is currently unused but will be used later for route matching.
|
|
2
|
+
/**
|
|
3
|
+
* Matches route path definitions (potentially containing parameters and wildcards)
|
|
4
|
+
* against actual navigation paths.
|
|
5
|
+
*
|
|
6
|
+
* Supports `:param` segments for named parameters and `**` for wildcard matching.
|
|
7
|
+
*/
|
|
8
|
+
class RouteMatcher {
|
|
9
|
+
private static _instance: RouteMatcher = new RouteMatcher();
|
|
10
|
+
|
|
11
|
+
static get instance(): RouteMatcher {
|
|
12
|
+
return RouteMatcher._instance;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** @internal visible for testing */
|
|
16
|
+
static setInstance(instance: RouteMatcher): void {
|
|
17
|
+
RouteMatcher._instance = instance;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks whether the given `routePath` definition matches the given `actualPath`.
|
|
22
|
+
*
|
|
23
|
+
* The `routePath` definition can contain parameters in the form of `:param`,
|
|
24
|
+
* or `**` for a wildcard parameter.
|
|
25
|
+
*
|
|
26
|
+
* Returns `true` if the `actualPath` matches the `routePath`, otherwise `false`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* RouteMatcher.instance.match('/users', '/users'); // true
|
|
31
|
+
* RouteMatcher.instance.match('/user/:id', '/user/123'); // true
|
|
32
|
+
* RouteMatcher.instance.match('/user/**', '/user/123/profile'); // true
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
match(routePath: string | null, actualPath: string | null): boolean {
|
|
36
|
+
if (routePath == null || actualPath == null) {
|
|
37
|
+
return routePath === actualPath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const routePathSegments = this.segmentPath(routePath);
|
|
41
|
+
const actualPathSegments = this.segmentPath(actualPath);
|
|
42
|
+
|
|
43
|
+
const hasWildcard = routePathSegments.includes('**');
|
|
44
|
+
|
|
45
|
+
if (routePathSegments.length !== actualPathSegments.length && !hasWildcard) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (let i = 0; i < routePathSegments.length; i++) {
|
|
50
|
+
const routeSegment = routePathSegments[i];
|
|
51
|
+
|
|
52
|
+
const isWildcard = routeSegment === '**';
|
|
53
|
+
const isParameter = routeSegment.startsWith(':');
|
|
54
|
+
|
|
55
|
+
const noMoreActualSegments = i >= actualPathSegments.length;
|
|
56
|
+
|
|
57
|
+
if (noMoreActualSegments) {
|
|
58
|
+
return isWildcard;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isParameter) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (isWildcard) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (routeSegment !== actualPathSegments[i]) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private segmentPath(path: string): string[] {
|
|
78
|
+
const pathWithoutQuery = path.split('?')[0];
|
|
79
|
+
return pathWithoutQuery.split('/').filter((segment) => segment.length > 0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default RouteMatcher;
|