@dreamhorizonorg/pulse-react-native 0.0.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.
Files changed (118) hide show
  1. package/LICENSE +20 -0
  2. package/PulseReactNativeOtel.podspec +21 -0
  3. package/README.md +900 -0
  4. package/android/build.gradle +97 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/proguard-rules.pro +108 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/java/com/pulsereactnativeotel/PulseOtelConstants.kt +20 -0
  9. package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelLogger.kt +73 -0
  10. package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelModule.kt +85 -0
  11. package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelPackage.kt +33 -0
  12. package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelTracer.kt +127 -0
  13. package/ios/PulseReactNativeOtel.h +5 -0
  14. package/ios/PulseReactNativeOtel.mm +100 -0
  15. package/lib/module/NativePulseReactNativeOtel.js +5 -0
  16. package/lib/module/NativePulseReactNativeOtel.js.map +1 -0
  17. package/lib/module/config.js +55 -0
  18. package/lib/module/config.js.map +1 -0
  19. package/lib/module/errorBoundary.js +62 -0
  20. package/lib/module/errorBoundary.js.map +1 -0
  21. package/lib/module/errorHandler.js +112 -0
  22. package/lib/module/errorHandler.js.map +1 -0
  23. package/lib/module/events.js +14 -0
  24. package/lib/module/events.js.map +1 -0
  25. package/lib/module/global.d.js +4 -0
  26. package/lib/module/global.d.js.map +1 -0
  27. package/lib/module/globalAttributes.js +13 -0
  28. package/lib/module/globalAttributes.js.map +1 -0
  29. package/lib/module/index.js +27 -0
  30. package/lib/module/index.js.map +1 -0
  31. package/lib/module/initialization.js +18 -0
  32. package/lib/module/initialization.js.map +1 -0
  33. package/lib/module/network-interceptor/initialization.js +25 -0
  34. package/lib/module/network-interceptor/initialization.js.map +1 -0
  35. package/lib/module/network-interceptor/network.interface.js +2 -0
  36. package/lib/module/network-interceptor/network.interface.js.map +1 -0
  37. package/lib/module/network-interceptor/request-tracker-fetch.js +72 -0
  38. package/lib/module/network-interceptor/request-tracker-fetch.js.map +1 -0
  39. package/lib/module/network-interceptor/request-tracker-xhr.js +75 -0
  40. package/lib/module/network-interceptor/request-tracker-xhr.js.map +1 -0
  41. package/lib/module/network-interceptor/request-tracker.js +25 -0
  42. package/lib/module/network-interceptor/request-tracker.js.map +1 -0
  43. package/lib/module/network-interceptor/span-helpers.js +62 -0
  44. package/lib/module/network-interceptor/span-helpers.js.map +1 -0
  45. package/lib/module/network-interceptor/url-helper.js +127 -0
  46. package/lib/module/network-interceptor/url-helper.js.map +1 -0
  47. package/lib/module/pulse.interface.js +2 -0
  48. package/lib/module/pulse.interface.js.map +1 -0
  49. package/lib/module/reactNavigation.js +100 -0
  50. package/lib/module/reactNavigation.js.map +1 -0
  51. package/lib/module/trace.js +75 -0
  52. package/lib/module/trace.js.map +1 -0
  53. package/lib/module/user.js +23 -0
  54. package/lib/module/user.js.map +1 -0
  55. package/lib/module/utility.js +34 -0
  56. package/lib/module/utility.js.map +1 -0
  57. package/lib/typescript/src/NativePulseReactNativeOtel.d.ts +31 -0
  58. package/lib/typescript/src/NativePulseReactNativeOtel.d.ts.map +1 -0
  59. package/lib/typescript/src/config.d.ts +14 -0
  60. package/lib/typescript/src/config.d.ts.map +1 -0
  61. package/lib/typescript/src/errorBoundary.d.ts +26 -0
  62. package/lib/typescript/src/errorBoundary.d.ts.map +1 -0
  63. package/lib/typescript/src/errorHandler.d.ts +4 -0
  64. package/lib/typescript/src/errorHandler.d.ts.map +1 -0
  65. package/lib/typescript/src/events.d.ts +3 -0
  66. package/lib/typescript/src/events.d.ts.map +1 -0
  67. package/lib/typescript/src/globalAttributes.d.ts +4 -0
  68. package/lib/typescript/src/globalAttributes.d.ts.map +1 -0
  69. package/lib/typescript/src/index.d.ts +30 -0
  70. package/lib/typescript/src/index.d.ts.map +1 -0
  71. package/lib/typescript/src/initialization.d.ts +3 -0
  72. package/lib/typescript/src/initialization.d.ts.map +1 -0
  73. package/lib/typescript/src/network-interceptor/initialization.d.ts +3 -0
  74. package/lib/typescript/src/network-interceptor/initialization.d.ts.map +1 -0
  75. package/lib/typescript/src/network-interceptor/network.interface.d.ts +29 -0
  76. package/lib/typescript/src/network-interceptor/network.interface.d.ts.map +1 -0
  77. package/lib/typescript/src/network-interceptor/request-tracker-fetch.d.ts +7 -0
  78. package/lib/typescript/src/network-interceptor/request-tracker-fetch.d.ts.map +1 -0
  79. package/lib/typescript/src/network-interceptor/request-tracker-xhr.d.ts +4 -0
  80. package/lib/typescript/src/network-interceptor/request-tracker-xhr.d.ts.map +1 -0
  81. package/lib/typescript/src/network-interceptor/request-tracker.d.ts +9 -0
  82. package/lib/typescript/src/network-interceptor/request-tracker.d.ts.map +1 -0
  83. package/lib/typescript/src/network-interceptor/span-helpers.d.ts +7 -0
  84. package/lib/typescript/src/network-interceptor/span-helpers.d.ts.map +1 -0
  85. package/lib/typescript/src/network-interceptor/url-helper.d.ts +38 -0
  86. package/lib/typescript/src/network-interceptor/url-helper.d.ts.map +1 -0
  87. package/lib/typescript/src/pulse.interface.d.ts +8 -0
  88. package/lib/typescript/src/pulse.interface.d.ts.map +1 -0
  89. package/lib/typescript/src/reactNavigation.d.ts +10 -0
  90. package/lib/typescript/src/reactNavigation.d.ts.map +1 -0
  91. package/lib/typescript/src/trace.d.ts +19 -0
  92. package/lib/typescript/src/trace.d.ts.map +1 -0
  93. package/lib/typescript/src/user.d.ts +5 -0
  94. package/lib/typescript/src/user.d.ts.map +1 -0
  95. package/lib/typescript/src/utility.d.ts +8 -0
  96. package/lib/typescript/src/utility.d.ts.map +1 -0
  97. package/package.json +165 -0
  98. package/src/NativePulseReactNativeOtel.ts +57 -0
  99. package/src/config.ts +75 -0
  100. package/src/errorBoundary.tsx +92 -0
  101. package/src/errorHandler.ts +169 -0
  102. package/src/events.ts +15 -0
  103. package/src/global.d.ts +9 -0
  104. package/src/globalAttributes.ts +16 -0
  105. package/src/index.tsx +35 -0
  106. package/src/initialization.ts +18 -0
  107. package/src/network-interceptor/initialization.ts +28 -0
  108. package/src/network-interceptor/network.interface.ts +36 -0
  109. package/src/network-interceptor/request-tracker-fetch.ts +96 -0
  110. package/src/network-interceptor/request-tracker-xhr.ts +108 -0
  111. package/src/network-interceptor/request-tracker.ts +31 -0
  112. package/src/network-interceptor/span-helpers.ts +84 -0
  113. package/src/network-interceptor/url-helper.ts +155 -0
  114. package/src/pulse.interface.ts +14 -0
  115. package/src/reactNavigation.tsx +146 -0
  116. package/src/trace.ts +108 -0
  117. package/src/user.ts +24 -0
  118. package/src/utility.ts +36 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initialization.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/initialization.ts"],"names":[],"mappings":"AAIA,wBAAgB,4BAA4B,IAAI,IAAI,CAqBnD;AAED,eAAO,MAAM,+BAA+B,QAAO,OAAwB,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface RequestStartContext {
2
+ url: string;
3
+ method: string;
4
+ type: 'fetch' | 'xmlhttprequest';
5
+ baseUrl?: string;
6
+ }
7
+ export interface RequestEndContextSuccess {
8
+ status: number;
9
+ state: 'success';
10
+ }
11
+ export interface RequestEndContextError {
12
+ state: 'error';
13
+ status?: number;
14
+ error?: Error;
15
+ }
16
+ export type RequestEndContext = RequestEndContextSuccess | RequestEndContextError;
17
+ export type RequestStartCallback = (context: RequestStartContext) => {
18
+ onRequestEnd?: RequestEndCallback;
19
+ } | undefined;
20
+ export type RequestEndCallback = (context: RequestEndContext) => void;
21
+ export interface NetworkRequestInfo {
22
+ url: string;
23
+ method: string;
24
+ type: 'fetch' | 'xmlhttprequest';
25
+ status?: number;
26
+ state: 'success' | 'error';
27
+ error?: Error;
28
+ }
29
+ //# sourceMappingURL=network.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.interface.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/network.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GACzB,wBAAwB,GACxB,sBAAsB,CAAC;AAE3B,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,mBAAmB,KACzB;IAAE,YAAY,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf"}
@@ -0,0 +1,7 @@
1
+ import { RequestTracker } from './request-tracker';
2
+ interface GlobalWithFetch {
3
+ fetch: typeof fetch;
4
+ }
5
+ declare function createFetchRequestTracker(global: GlobalWithFetch): RequestTracker;
6
+ export default createFetchRequestTracker;
7
+ //# sourceMappingURL=request-tracker-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-tracker-fetch.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/request-tracker-fetch.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD,UAAU,eAAe;IACvB,KAAK,EAAE,OAAO,KAAK,CAAC;CACrB;AAsBD,iBAAS,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CA6D1E;AAED,eAAe,yBAAyB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { RequestTracker } from './request-tracker';
2
+ declare function createXmlHttpRequestTracker(xhr: typeof XMLHttpRequest): RequestTracker;
3
+ export default createXmlHttpRequestTracker;
4
+ //# sourceMappingURL=request-tracker-xhr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-tracker-xhr.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/request-tracker-xhr.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAcnD,iBAAS,2BAA2B,CAClC,GAAG,EAAE,OAAO,cAAc,GACzB,cAAc,CAqFhB;AAED,eAAe,2BAA2B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { RequestStartContext, RequestEndContext, RequestStartCallback } from './network.interface';
2
+ export declare class RequestTracker {
3
+ private callbacks;
4
+ onStart(startCallback: RequestStartCallback): void;
5
+ start(context: RequestStartContext): {
6
+ onRequestEnd: (endContext: RequestEndContext) => void;
7
+ };
8
+ }
9
+ //# sourceMappingURL=request-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-tracker.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/request-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAA8B;IAE/C,OAAO,CAAC,aAAa,EAAE,oBAAoB;IAI3C,KAAK,CAAC,OAAO,EAAE,mBAAmB;mCAQH,iBAAiB;;CASjD"}
@@ -0,0 +1,7 @@
1
+ import type { RequestStartContext, RequestEndContext } from './network.interface';
2
+ import type { Span } from '../index';
3
+ import type { PulseAttributes } from '../pulse.interface';
4
+ export declare function setNetworkSpanAttributes(span: Span, startContext: RequestStartContext, endContext: RequestEndContext): PulseAttributes;
5
+ export declare function createNetworkSpan(startContext: RequestStartContext, interceptorType: 'fetch' | 'xmlhttprequest'): Span;
6
+ export declare function completeNetworkSpan(span: Span, startContext: RequestStartContext, endContext: RequestEndContext, isError: boolean): void;
7
+ //# sourceMappingURL=span-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-helpers.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/span-helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,mBAAmB,EACjC,UAAU,EAAE,iBAAiB,GAC5B,eAAe,CA+BjB;AAED,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,mBAAmB,EACjC,eAAe,EAAE,OAAO,GAAG,gBAAgB,GAC1C,IAAI,CAcN;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,mBAAmB,EACjC,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,OAAO,GACf,IAAI,CAYN"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * URL parsing helper for React Native
3
+ * Provides consistent URL parsing across all RN versions
4
+ *
5
+ * React Native < 0.80 throws errors for URL properties like hostname, protocol, etc.
6
+ * This helper uses the same regex approach as RN 0.80+ to ensure compatibility.
7
+ *
8
+ * Based on: https://github.com/facebook/react-native/blob/v0.80.0/packages/react-native/Libraries/Blob/URL.js
9
+ */
10
+ export interface ParsedUrl {
11
+ protocol: string;
12
+ hostname: string;
13
+ host: string;
14
+ port: string;
15
+ pathname: string;
16
+ search: string;
17
+ hash: string;
18
+ href: string;
19
+ }
20
+ /**
21
+ * Parse a URL string into its components
22
+ * Returns null if URL is invalid or cannot be parsed
23
+ *
24
+ * This function is defensive and will return empty strings for any component
25
+ * that cannot be extracted, rather than throwing errors.
26
+ */
27
+ export declare function parseUrl(url: string): ParsedUrl | null;
28
+ /**
29
+ * Extract HTTP attributes from a URL string for OpenTelemetry span attributes
30
+ */
31
+ export declare function extractHttpAttributes(url: string): {
32
+ 'http.scheme'?: string;
33
+ 'http.host'?: string;
34
+ 'http.target'?: string;
35
+ 'net.peer.name'?: string;
36
+ 'net.peer.port'?: number;
37
+ };
38
+ //# sourceMappingURL=url-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-helper.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/url-helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAmBD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAqDtD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CA6CA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * OpenTelemetry attribute value types.
3
+ * Based on OpenTelemetry JavaScript SDK attribute types.
4
+ * @see https://github.com/open-telemetry/opentelemetry-js/blob/main/api/src/common/Attributes.ts
5
+ */
6
+ export type PulseAttributeValue = string | number | boolean | string[] | number[] | boolean[];
7
+ export type PulseAttributes = Record<string, PulseAttributeValue | undefined>;
8
+ //# sourceMappingURL=pulse.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse.interface.d.ts","sourceRoot":"","sources":["../../../src/pulse.interface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAC3B,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,EAAE,GACR,MAAM,EAAE,GACR,OAAO,EAAE,CAAC;AAEd,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface NavigationRoute {
2
+ name: string;
3
+ key: string;
4
+ params?: Record<string, any>;
5
+ }
6
+ export declare function createReactNavigationIntegration(): {
7
+ registerNavigationContainer: (maybeNavigationContainer: unknown) => void;
8
+ };
9
+ export type ReactNavigationIntegration = ReturnType<typeof createReactNavigationIntegration>;
10
+ //# sourceMappingURL=reactNavigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactNavigation.d.ts","sourceRoot":"","sources":["../../../src/reactNavigation.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAOD,wBAAgB,gCAAgC;4DAoElB,OAAO,KAChC,IAAI;EAyDR;AAED,MAAM,MAAM,0BAA0B,GAAG,UAAU,CACjD,OAAO,gCAAgC,CACxC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { PulseAttributes } from './pulse.interface';
2
+ export type SpanOptions = {
3
+ attributes?: PulseAttributes;
4
+ };
5
+ export declare enum SpanStatusCode {
6
+ OK = "OK",
7
+ ERROR = "ERROR",
8
+ UNSET = "UNSET"
9
+ }
10
+ export type Span = {
11
+ end: (statusCode?: SpanStatusCode) => void;
12
+ addEvent: (name: string, attributes?: PulseAttributes) => void;
13
+ setAttributes: (attributes?: PulseAttributes) => void;
14
+ recordException: (error: Error, attributes?: PulseAttributes) => void;
15
+ spanId?: string;
16
+ };
17
+ export declare function startSpan(name: string, options?: SpanOptions): Span;
18
+ export declare function trackSpan<T>(name: string, options: SpanOptions, fn: () => T | Promise<T>): T | Promise<T>;
19
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/trace.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF,oBAAY,cAAc;IACxB,EAAE,OAAO;IACT,KAAK,UAAU;IACf,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAEtE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CA4BnE;AAED,wBAAgB,SAAS,CAAC,CAAC,EACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBhB"}
@@ -0,0 +1,5 @@
1
+ import type { PulseAttributes } from './pulse.interface';
2
+ export declare function setUserId(id: string | null): void;
3
+ export declare function setUserProperty(name: string, value: string | null): void;
4
+ export declare function setUserProperties(properties: PulseAttributes): void;
5
+ //# sourceMappingURL=user.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../src/user.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAKjD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAKxE;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAKnE"}
@@ -0,0 +1,8 @@
1
+ export declare function nowMs(): number;
2
+ export declare function getAbsoluteUrl(url: string, baseUrl?: string): string;
3
+ export declare function extractErrorDetails(error: Error): {
4
+ message: string;
5
+ stackTrace: string;
6
+ errorType: string;
7
+ };
8
+ //# sourceMappingURL=utility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utility.d.ts","sourceRoot":"","sources":["../../../src/utility.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,IAAI,MAAM,CAI9B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBpE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAMA"}
package/package.json ADDED
@@ -0,0 +1,165 @@
1
+ {
2
+ "name": "@dreamhorizonorg/pulse-react-native",
3
+ "version": "0.0.1",
4
+ "description": "Production-grade observability SDK for React Native applications with OpenTelemetry support. Real-time monitoring, error tracking, performance insights, and distributed tracing.",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-pulse-react-native-otel-example",
36
+ "test": "jest",
37
+ "typecheck": "tsc",
38
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
39
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
40
+ "prepare": "bob build",
41
+ "release": "release-it --only-version"
42
+ },
43
+ "keywords": [
44
+ "react-native",
45
+ "opentelemetry",
46
+ "observability",
47
+ "monitoring",
48
+ "error-tracking",
49
+ "performance",
50
+ "tracing",
51
+ "analytics",
52
+ "ios",
53
+ "android"
54
+ ],
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/dream-horizon-org/pulse.git",
58
+ "directory": "pulse-react-native-otel"
59
+ },
60
+ "author": "DreamHorizon <https://dreamhorizon.org>",
61
+ "license": "MIT",
62
+ "bugs": {
63
+ "url": "https://github.com/dream-horizon-org/pulse/issues"
64
+ },
65
+ "homepage": "https://github.com/dream-horizon-org/pulse/tree/main/pulse-react-native-otel#readme",
66
+ "publishConfig": {
67
+ "registry": "https://registry.npmjs.org/"
68
+ },
69
+ "devDependencies": {
70
+ "@commitlint/config-conventional": "^19.8.1",
71
+ "@eslint/compat": "^1.3.2",
72
+ "@eslint/eslintrc": "^3.3.1",
73
+ "@eslint/js": "^9.35.0",
74
+ "@evilmartians/lefthook": "^1.12.3",
75
+ "@react-native-community/cli": "20.0.1",
76
+ "@react-native/babel-preset": "0.81.1",
77
+ "@react-native/eslint-config": "^0.81.1",
78
+ "@release-it/conventional-changelog": "^10.0.1",
79
+ "@types/jest": "^29.5.14",
80
+ "@types/react": "^19.1.0",
81
+ "commitlint": "^19.8.1",
82
+ "del-cli": "^6.0.0",
83
+ "eslint": "^9.35.0",
84
+ "eslint-config-prettier": "^10.1.8",
85
+ "eslint-plugin-prettier": "^5.5.4",
86
+ "jest": "^29.7.0",
87
+ "prettier": "^3.6.2",
88
+ "react": "19.1.0",
89
+ "react-native": "0.81.1",
90
+ "react-native-builder-bob": "0.30.2",
91
+ "release-it": "^19.0.4",
92
+ "turbo": "^2.5.6",
93
+ "typescript": "^5.9.2"
94
+ },
95
+ "peerDependencies": {
96
+ "react": "*",
97
+ "react-native": "*"
98
+ },
99
+ "workspaces": [
100
+ "example"
101
+ ],
102
+ "packageManager": "yarn@3.6.1",
103
+ "commitlint": {
104
+ "extends": [
105
+ "@commitlint/config-conventional"
106
+ ]
107
+ },
108
+ "release-it": {
109
+ "git": {
110
+ "commitMessage": "chore: release ${version}",
111
+ "tagName": "v${version}"
112
+ },
113
+ "npm": {
114
+ "publish": true
115
+ },
116
+ "github": {
117
+ "release": true
118
+ },
119
+ "plugins": {
120
+ "@release-it/conventional-changelog": {
121
+ "preset": {
122
+ "name": "angular"
123
+ }
124
+ }
125
+ }
126
+ },
127
+ "prettier": {
128
+ "quoteProps": "consistent",
129
+ "singleQuote": true,
130
+ "tabWidth": 2,
131
+ "trailingComma": "es5",
132
+ "useTabs": false
133
+ },
134
+ "react-native-builder-bob": {
135
+ "source": "src",
136
+ "output": "lib",
137
+ "targets": [
138
+ [
139
+ "module",
140
+ {
141
+ "esm": true
142
+ }
143
+ ],
144
+ [
145
+ "typescript",
146
+ {
147
+ "project": "tsconfig.build.json"
148
+ }
149
+ ]
150
+ ]
151
+ },
152
+ "codegenConfig": {
153
+ "name": "PulseReactNativeOtelSpec",
154
+ "type": "modules",
155
+ "jsSrcsDir": "src",
156
+ "android": {
157
+ "javaPackageName": "com.pulsereactnativeotel"
158
+ }
159
+ },
160
+ "create-react-native-library": {
161
+ "languages": "kotlin-objc",
162
+ "type": "turbo-module",
163
+ "version": "0.54.8"
164
+ }
165
+ }
@@ -0,0 +1,57 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ export interface Spec extends TurboModule {
4
+ /** Check if native SDK is initialized */
5
+ isInitialized(): boolean;
6
+
7
+ /** Track a custom event with properties. */
8
+ trackEvent(
9
+ event: string,
10
+ observedTimeMs: number,
11
+ properties?: Object
12
+ ): boolean;
13
+
14
+ /** Report a JS exception (message + stack, with fatal flag). */
15
+ /** This function was made synchronous to attach current span context to the error event. Since span is created synchronously on mqt_js thread.*/
16
+ reportException(
17
+ errorMessage: string,
18
+ observedTimeMs: number,
19
+ stackTrace: string,
20
+ isFatal: boolean,
21
+ errorType: string,
22
+ attributes?: Object
23
+ ): boolean;
24
+
25
+ /** Start an active span; returns spanId (simplified). */
26
+ startSpan(name: string, attributes?: Object): string;
27
+
28
+ /** End a span with optional status code. */
29
+ endSpan(spanId: string, statusCode?: string): boolean;
30
+
31
+ /** Add an event to a span. */
32
+ addSpanEvent(spanId: string, name: string, attributes?: Object): boolean;
33
+
34
+ /** Batch set attributes on a span. */
35
+ setSpanAttributes(spanId: string, attributes?: Object): boolean;
36
+
37
+ /** Record an exception on a span. */
38
+ recordSpanException(
39
+ spanId: string,
40
+ errorMessage: string,
41
+ stackTrace?: string
42
+ ): boolean;
43
+
44
+ /** Set user id for the session. Setting null will reset the id */
45
+ setUserId(id: string | null): void;
46
+
47
+ /** Set a single user property for this session */
48
+ setUserProperty(name: string, value: string | null): void;
49
+
50
+ /** Set multiple user properties for this session */
51
+ setUserProperties(properties: Object): void;
52
+
53
+ /** Trigger ANR test (freezes main thread for 6 seconds) */
54
+ triggerAnr(): void;
55
+ }
56
+
57
+ export default TurboModuleRegistry.getEnforcing<Spec>('PulseReactNativeOtel');
package/src/config.ts ADDED
@@ -0,0 +1,75 @@
1
+ import { setupErrorHandler } from './errorHandler';
2
+ import { isSupportedPlatform } from './initialization';
3
+ import {
4
+ createReactNavigationIntegration,
5
+ type ReactNavigationIntegration,
6
+ } from './reactNavigation';
7
+ import { initializeNetworkInterceptor } from './network-interceptor/initialization';
8
+
9
+ export type PulseConfig = {
10
+ autoDetectExceptions?: boolean;
11
+ autoDetectNavigation?: boolean;
12
+ autoDetectNetwork?: boolean;
13
+ };
14
+
15
+ export type PulseStartOptions = {
16
+ autoDetectExceptions?: boolean;
17
+ autoDetectNavigation?: boolean;
18
+ autoDetectNetwork?: boolean;
19
+ };
20
+
21
+ const defaultConfig: PulseConfig = {
22
+ autoDetectExceptions: true,
23
+ autoDetectNavigation: true,
24
+ autoDetectNetwork: true,
25
+ };
26
+
27
+ let currentConfig: PulseConfig = { ...defaultConfig };
28
+
29
+ function configure(config: PulseConfig): void {
30
+ currentConfig = {
31
+ ...currentConfig,
32
+ ...config,
33
+ };
34
+ setupErrorHandler(currentConfig.autoDetectExceptions ?? true);
35
+
36
+ if (currentConfig.autoDetectNetwork) {
37
+ initializeNetworkInterceptor();
38
+ }
39
+ }
40
+
41
+ export function start(options?: PulseStartOptions): void {
42
+ if (!isSupportedPlatform()) {
43
+ return;
44
+ }
45
+ const autoDetectExceptions = options?.autoDetectExceptions ?? true;
46
+ const autoDetectNavigation = options?.autoDetectNavigation ?? true;
47
+ const autoDetectNetwork = options?.autoDetectNetwork ?? true;
48
+ configure({
49
+ autoDetectExceptions,
50
+ autoDetectNavigation,
51
+ autoDetectNetwork,
52
+ });
53
+ }
54
+
55
+ export function createNavigationIntegrationWithConfig(): ReactNavigationIntegration {
56
+ if (!isSupportedPlatform()) {
57
+ return {
58
+ registerNavigationContainer: (_: unknown) => {},
59
+ };
60
+ }
61
+ if (!currentConfig.autoDetectNavigation) {
62
+ console.warn(
63
+ '[Pulse Navigation] auto-detection disabled via Pulse.start; createNavigationIntegration() returning no-op.'
64
+ );
65
+ const noop: ReactNavigationIntegration = {
66
+ registerNavigationContainer: (_: unknown) => {
67
+ console.warn(
68
+ '[Pulse Navigation] auto-detection disabled via Pulse.start; registerNavigationContainer() returning no-op.'
69
+ );
70
+ },
71
+ };
72
+ return noop;
73
+ }
74
+ return createReactNavigationIntegration();
75
+ }
@@ -0,0 +1,92 @@
1
+ import * as React from 'react';
2
+ import { Pulse } from './index';
3
+
4
+ export const UNKNOWN_COMPONENT = 'unknown';
5
+ const COMPONENT_STACK_UNAVAILABLE = '<component stack unavailable>';
6
+
7
+ export type FallbackRender = (errorData: {
8
+ error: unknown;
9
+ componentStack: string;
10
+ }) => React.ReactElement;
11
+
12
+ export type ErrorBoundaryProps = {
13
+ children?: React.ReactNode | (() => React.ReactNode);
14
+ fallback?: React.ReactElement | FallbackRender | undefined;
15
+ onError?: ((error: unknown, componentStack: string) => void) | undefined;
16
+ };
17
+
18
+ type ErrorBoundaryState =
19
+ | {
20
+ componentStack: null;
21
+ error: null;
22
+ }
23
+ | {
24
+ componentStack: string;
25
+ error: unknown;
26
+ };
27
+
28
+ const INITIAL_STATE: ErrorBoundaryState = {
29
+ componentStack: null,
30
+ error: null,
31
+ };
32
+
33
+ export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
34
+ public state: ErrorBoundaryState = INITIAL_STATE;
35
+
36
+ public componentDidCatch(error: unknown, errorInfo: React.ErrorInfo): void {
37
+ const componentStack = errorInfo.componentStack || COMPONENT_STACK_UNAVAILABLE;
38
+ const { onError } = this.props;
39
+
40
+ // Error is handled if a fallback is provided, otherwise it's unhandled (fatal)
41
+ const handled = !!this.props.fallback;
42
+
43
+ const errorToReport = error instanceof Error ? error : new Error(String(error));
44
+ Pulse.reportException(errorToReport, !handled);
45
+
46
+ if (onError) {
47
+ onError(error, componentStack);
48
+ }
49
+
50
+ this.setState({ error, componentStack });
51
+ }
52
+
53
+ public render(): React.ReactNode {
54
+ const { fallback, children } = this.props;
55
+ const state = this.state;
56
+
57
+ if (state.componentStack === null) {
58
+ return typeof children === 'function' ? children() : children;
59
+ }
60
+
61
+ const element =
62
+ typeof fallback === 'function'
63
+ ? React.createElement(fallback, {
64
+ error: state.error,
65
+ componentStack: state.componentStack,
66
+ })
67
+ : fallback;
68
+
69
+ if (React.isValidElement(element)) {
70
+ return element;
71
+ }
72
+
73
+ return null;
74
+ }
75
+ }
76
+
77
+ export function withErrorBoundary<P extends Record<string, any>>(
78
+ WrappedComponent: React.ComponentType<P>,
79
+ errorBoundaryOptions: ErrorBoundaryProps,
80
+ ): React.FC<P> {
81
+ const componentDisplayName = WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;
82
+
83
+ const Wrapped = React.memo((props: P) => (
84
+ <ErrorBoundary {...errorBoundaryOptions}>
85
+ <WrappedComponent {...props} />
86
+ </ErrorBoundary>
87
+ )) as unknown as React.FC<P>;
88
+
89
+ Wrapped.displayName = `errorBoundary(${componentDisplayName})`;
90
+
91
+ return Wrapped;
92
+ }