@dreamhorizonorg/pulse-react-native 0.0.1 ā 0.0.3
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/PulseReactNativeOtel.podspec +1 -1
- package/README.md +34 -879
- package/android/build.gradle +10 -15
- package/android/proguard-rules.pro +3 -99
- package/android/src/main/java/com/pulsereactnativeotel/Pulse.kt +89 -0
- package/android/src/main/java/com/pulsereactnativeotel/PulseOtelConstants.kt +1 -1
- package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelLogger.kt +3 -1
- package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelModule.kt +69 -3
- package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelPackage.kt +1 -1
- package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelTracer.kt +24 -8
- package/android/src/main/java/com/pulsereactnativeotel/ReactNativeScreenAttributesLogRecordProcessor.kt +21 -0
- package/android/src/main/java/com/pulsereactnativeotel/ReactNativeScreenAttributesSpanProcessor.kt +30 -0
- package/android/src/main/java/com/pulsereactnativeotel/ReactNativeScreenNameTracker.kt +17 -0
- package/app.plugin.js +1 -0
- package/ios/PulseReactNativeOtel.mm +7 -1
- package/lib/module/NativePulseReactNativeOtel.js.map +1 -1
- package/lib/module/config.js +57 -19
- package/lib/module/config.js.map +1 -1
- package/lib/module/errorBoundary.js.map +1 -1
- package/lib/module/events.js +6 -0
- package/lib/module/events.js.map +1 -1
- package/lib/module/index.js +4 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/navigation/index.js +179 -0
- package/lib/module/navigation/index.js.map +1 -0
- package/lib/module/navigation/navigation.interface.js +8 -0
- package/lib/module/navigation/navigation.interface.js.map +1 -0
- package/lib/module/navigation/screen-interactive.js +101 -0
- package/lib/module/navigation/screen-interactive.js.map +1 -0
- package/lib/module/navigation/screen-load.js +67 -0
- package/lib/module/navigation/screen-load.js.map +1 -0
- package/lib/module/navigation/screen-session.js +60 -0
- package/lib/module/navigation/screen-session.js.map +1 -0
- package/lib/module/navigation/useNavigationTracking.js +34 -0
- package/lib/module/navigation/useNavigationTracking.js.map +1 -0
- package/lib/module/navigation/utils.js +17 -0
- package/lib/module/navigation/utils.js.map +1 -0
- package/lib/module/network-interceptor/graphql-helper.js +92 -0
- package/lib/module/network-interceptor/graphql-helper.js.map +1 -0
- package/lib/module/network-interceptor/header-helper.js +24 -0
- package/lib/module/network-interceptor/header-helper.js.map +1 -0
- package/lib/module/network-interceptor/initialization.js +18 -1
- package/lib/module/network-interceptor/initialization.js.map +1 -1
- package/lib/module/network-interceptor/request-tracker-xhr.js +61 -4
- package/lib/module/network-interceptor/request-tracker-xhr.js.map +1 -1
- package/lib/module/network-interceptor/span-helpers.js +36 -16
- package/lib/module/network-interceptor/span-helpers.js.map +1 -1
- package/lib/module/network-interceptor/url-helper.js +58 -2
- package/lib/module/network-interceptor/url-helper.js.map +1 -1
- package/lib/module/pulse.constants.js +47 -0
- package/lib/module/pulse.constants.js.map +1 -0
- package/lib/module/trace.js +17 -2
- package/lib/module/trace.js.map +1 -1
- package/lib/typescript/plugin/src/index.d.ts +5 -0
- package/lib/typescript/plugin/src/index.d.ts.map +1 -0
- package/lib/typescript/plugin/src/types.d.ts +27 -0
- package/lib/typescript/plugin/src/types.d.ts.map +1 -0
- package/lib/typescript/plugin/src/utils.d.ts +10 -0
- package/lib/typescript/plugin/src/utils.d.ts.map +1 -0
- package/lib/typescript/plugin/src/withAndroidPulse.d.ts +4 -0
- package/lib/typescript/plugin/src/withAndroidPulse.d.ts.map +1 -0
- package/lib/typescript/src/NativePulseReactNativeOtel.d.ts +15 -2
- package/lib/typescript/src/NativePulseReactNativeOtel.d.ts.map +1 -1
- package/lib/typescript/src/config.d.ts +14 -8
- package/lib/typescript/src/config.d.ts.map +1 -1
- package/lib/typescript/src/errorBoundary.d.ts.map +1 -1
- package/lib/typescript/src/events.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/index.d.ts +13 -0
- package/lib/typescript/src/navigation/index.d.ts.map +1 -0
- package/lib/typescript/src/navigation/navigation.interface.d.ts +18 -0
- package/lib/typescript/src/navigation/navigation.interface.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen-interactive.d.ts +16 -0
- package/lib/typescript/src/navigation/screen-interactive.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen-load.d.ts +13 -0
- package/lib/typescript/src/navigation/screen-load.d.ts.map +1 -0
- package/lib/typescript/src/navigation/screen-session.d.ts +15 -0
- package/lib/typescript/src/navigation/screen-session.d.ts.map +1 -0
- package/lib/typescript/src/navigation/useNavigationTracking.d.ts +5 -0
- package/lib/typescript/src/navigation/useNavigationTracking.d.ts.map +1 -0
- package/lib/typescript/src/navigation/utils.d.ts +8 -0
- package/lib/typescript/src/navigation/utils.d.ts.map +1 -0
- package/lib/typescript/src/network-interceptor/graphql-helper.d.ts +8 -0
- package/lib/typescript/src/network-interceptor/graphql-helper.d.ts.map +1 -0
- package/lib/typescript/src/network-interceptor/header-helper.d.ts +15 -0
- package/lib/typescript/src/network-interceptor/header-helper.d.ts.map +1 -0
- package/lib/typescript/src/network-interceptor/initialization.d.ts +4 -1
- package/lib/typescript/src/network-interceptor/initialization.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/network.interface.d.ts +3 -0
- package/lib/typescript/src/network-interceptor/network.interface.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/request-tracker-xhr.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/span-helpers.d.ts +1 -1
- package/lib/typescript/src/network-interceptor/span-helpers.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/url-helper.d.ts +9 -0
- package/lib/typescript/src/network-interceptor/url-helper.d.ts.map +1 -1
- package/lib/typescript/src/pulse.constants.d.ts +43 -0
- package/lib/typescript/src/pulse.constants.d.ts.map +1 -0
- package/lib/typescript/src/pulse.interface.d.ts +2 -1
- package/lib/typescript/src/pulse.interface.d.ts.map +1 -1
- package/lib/typescript/src/trace.d.ts +7 -0
- package/lib/typescript/src/trace.d.ts.map +1 -1
- package/package.json +29 -9
- package/plugin/build/index.d.ts +4 -0
- package/plugin/build/index.js +10 -0
- package/plugin/build/types.d.ts +26 -0
- package/plugin/build/types.js +2 -0
- package/plugin/build/utils.d.ts +9 -0
- package/plugin/build/utils.js +102 -0
- package/plugin/build/withAndroidPulse.d.ts +3 -0
- package/plugin/build/withAndroidPulse.js +53 -0
- package/scripts/pulse-cli.js +82 -0
- package/scripts/uploadService.js +122 -0
- package/scripts/utils.js +125 -0
- package/src/NativePulseReactNativeOtel.ts +18 -2
- package/src/config.ts +94 -23
- package/src/errorBoundary.tsx +11 -5
- package/src/events.ts +7 -0
- package/src/global.d.ts +0 -1
- package/src/index.tsx +7 -4
- package/src/navigation/index.ts +335 -0
- package/src/navigation/navigation.interface.ts +26 -0
- package/src/navigation/screen-interactive.ts +149 -0
- package/src/navigation/screen-load.ts +97 -0
- package/src/navigation/screen-session.ts +87 -0
- package/src/navigation/useNavigationTracking.ts +59 -0
- package/src/navigation/utils.ts +19 -0
- package/src/network-interceptor/graphql-helper.ts +110 -0
- package/src/network-interceptor/header-helper.ts +26 -0
- package/src/network-interceptor/initialization.ts +22 -1
- package/src/network-interceptor/network.interface.ts +3 -0
- package/src/network-interceptor/request-tracker-xhr.ts +93 -3
- package/src/network-interceptor/span-helpers.ts +47 -18
- package/src/network-interceptor/url-helper.ts +67 -1
- package/src/pulse.constants.ts +52 -0
- package/src/pulse.interface.ts +6 -1
- package/src/trace.ts +25 -2
- package/LICENSE +0 -20
- package/lib/module/network-interceptor/request-tracker-fetch.js +0 -72
- package/lib/module/network-interceptor/request-tracker-fetch.js.map +0 -1
- package/lib/module/reactNavigation.js +0 -100
- package/lib/module/reactNavigation.js.map +0 -1
- package/lib/typescript/src/network-interceptor/request-tracker-fetch.d.ts +0 -7
- package/lib/typescript/src/network-interceptor/request-tracker-fetch.d.ts.map +0 -1
- package/lib/typescript/src/reactNavigation.d.ts +0 -10
- package/lib/typescript/src/reactNavigation.d.ts.map +0 -1
- package/src/network-interceptor/request-tracker-fetch.ts +0 -96
- package/src/reactNavigation.tsx +0 -146
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Based on: https://github.com/facebook/react-native/blob/v0.80.0/packages/react-native/Libraries/Blob/URL.js
|
|
9
9
|
*/
|
|
10
|
+
export declare class SearchParams {
|
|
11
|
+
private params;
|
|
12
|
+
constructor(search: string);
|
|
13
|
+
get(name: string): string | null;
|
|
14
|
+
has(name: string): boolean;
|
|
15
|
+
keys(): string[];
|
|
16
|
+
values(): string[];
|
|
17
|
+
}
|
|
10
18
|
export interface ParsedUrl {
|
|
11
19
|
protocol: string;
|
|
12
20
|
hostname: string;
|
|
@@ -16,6 +24,7 @@ export interface ParsedUrl {
|
|
|
16
24
|
search: string;
|
|
17
25
|
hash: string;
|
|
18
26
|
href: string;
|
|
27
|
+
searchParams: SearchParams;
|
|
19
28
|
}
|
|
20
29
|
/**
|
|
21
30
|
* Parse a URL string into its components
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"url-helper.d.ts","sourceRoot":"","sources":["../../../../src/network-interceptor/url-helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAkC;gBAEpC,MAAM,EAAE,MAAM;IAyC1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIhC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,IAAI,IAAI,MAAM,EAAE;IAIhB,MAAM,IAAI,MAAM,EAAE;CAGnB;AAED,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;IACb,YAAY,EAAE,YAAY,CAAC;CAC5B;AAmBD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAyDtD;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,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for Pulse React Native OpenTelemetry integration
|
|
3
|
+
*/
|
|
4
|
+
export declare enum SPAN_NAMES {
|
|
5
|
+
SCREEN_SESSION = "ScreenSession",
|
|
6
|
+
NAVIGATED = "Navigated",
|
|
7
|
+
SCREEN_INTERACTIVE = "ScreenInteractive"
|
|
8
|
+
}
|
|
9
|
+
export declare enum ATTRIBUTE_KEYS {
|
|
10
|
+
PULSE_TYPE = "pulse.type",
|
|
11
|
+
SCREEN_NAME = "screen.name",
|
|
12
|
+
ROUTE_KEY = "routeKey",
|
|
13
|
+
LAST_SCREEN_NAME = "last.screen.name",
|
|
14
|
+
ROUTE_HAS_BEEN_SEEN = "routeHasBeenSeen",
|
|
15
|
+
PLATFORM = "platform",
|
|
16
|
+
GRAPHQL_OPERATION_NAME = "graphql.operation.name",
|
|
17
|
+
GRAPHQL_OPERATION_TYPE = "graphql.operation.type",
|
|
18
|
+
HTTP_METHOD = "http.method",
|
|
19
|
+
HTTP_URL = "http.url",
|
|
20
|
+
HTTP_STATUS_CODE = "http.status_code",
|
|
21
|
+
HTTP_REQUEST_TYPE = "http.request.type",
|
|
22
|
+
HTTP_REQUEST_HEADER = "http.request.header",
|
|
23
|
+
HTTP_RESPONSE_HEADER = "http.response.header",
|
|
24
|
+
ERROR_MESSAGE = "error.message",
|
|
25
|
+
ERROR_STACK = "error.stack"
|
|
26
|
+
}
|
|
27
|
+
export declare enum PULSE_TYPES {
|
|
28
|
+
SCREEN_SESSION = "screen_session",
|
|
29
|
+
SCREEN_LOAD = "screen_load",
|
|
30
|
+
SCREEN_INTERACTIVE = "screen_interactive",
|
|
31
|
+
NETWORK = "network"
|
|
32
|
+
}
|
|
33
|
+
export declare const PULSE_FEATURE_NAMES: {
|
|
34
|
+
readonly RN_SCREEN_LOAD: "rn_screen_load";
|
|
35
|
+
readonly SCREEN_SESSION: "screen_session";
|
|
36
|
+
readonly RN_SCREEN_INTERACTIVE: "rn_screen_interactive";
|
|
37
|
+
readonly NETWORK_INSTRUMENTATION: "network_instrumentation";
|
|
38
|
+
readonly CUSTOM_EVENTS: "custom_events";
|
|
39
|
+
readonly JS_CRASH: "js_crash";
|
|
40
|
+
};
|
|
41
|
+
export type PulseFeatureName = (typeof PULSE_FEATURE_NAMES)[keyof typeof PULSE_FEATURE_NAMES];
|
|
42
|
+
export type NavigationFeatureName = typeof PULSE_FEATURE_NAMES.SCREEN_SESSION | typeof PULSE_FEATURE_NAMES.RN_SCREEN_LOAD | typeof PULSE_FEATURE_NAMES.RN_SCREEN_INTERACTIVE;
|
|
43
|
+
//# sourceMappingURL=pulse.constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pulse.constants.d.ts","sourceRoot":"","sources":["../../../src/pulse.constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oBAAY,UAAU;IACpB,cAAc,kBAAkB;IAChC,SAAS,cAAc;IACvB,kBAAkB,sBAAsB;CACzC;AAED,oBAAY,cAAc;IACxB,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,SAAS,aAAa;IACtB,gBAAgB,qBAAqB;IACrC,mBAAmB,qBAAqB;IACxC,QAAQ,aAAa;IACrB,sBAAsB,2BAA2B;IACjD,sBAAsB,2BAA2B;IACjD,WAAW,gBAAgB;IAC3B,QAAQ,aAAa;IACrB,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,oBAAoB,yBAAyB;IAC7C,aAAa,kBAAkB;IAC/B,WAAW,gBAAgB;CAC5B;AAED,oBAAY,WAAW;IACrB,cAAc,mBAAmB;IACjC,WAAW,gBAAgB;IAC3B,kBAAkB,uBAAuB;IACzC,OAAO,YAAY;CACpB;AAED,eAAO,MAAM,mBAAmB;;;;;;;CAOtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAC;AAEjE,MAAM,MAAM,qBAAqB,GAC7B,OAAO,mBAAmB,CAAC,cAAc,GACzC,OAAO,mBAAmB,CAAC,cAAc,GACzC,OAAO,mBAAmB,CAAC,qBAAqB,CAAC"}
|
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
* @see https://github.com/open-telemetry/opentelemetry-js/blob/main/api/src/common/Attributes.ts
|
|
5
5
|
*/
|
|
6
6
|
export type PulseAttributeValue = string | number | boolean | string[] | number[] | boolean[];
|
|
7
|
-
export type PulseAttributes = Record<string, PulseAttributeValue | undefined>;
|
|
7
|
+
export type PulseAttributes = Record<string, PulseAttributeValue | undefined | null>;
|
|
8
|
+
export type PulseFeatureConfig = Record<string, boolean> | null | undefined;
|
|
8
9
|
//# sourceMappingURL=pulse.interface.d.ts.map
|
|
@@ -1 +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,
|
|
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,CAClC,MAAM,EACN,mBAAmB,GAAG,SAAS,GAAG,IAAI,CACvC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { PulseAttributes } from './pulse.interface';
|
|
2
|
+
/**
|
|
3
|
+
* Options for starting a span.
|
|
4
|
+
* @param attributes - Attributes to set on the span.
|
|
5
|
+
* @param inheritContext - Controls whether or not the new span will be parented in the existing (current) context. If false, a new context is created.
|
|
6
|
+
*/
|
|
2
7
|
export type SpanOptions = {
|
|
3
8
|
attributes?: PulseAttributes;
|
|
9
|
+
inheritContext?: boolean;
|
|
4
10
|
};
|
|
5
11
|
export declare enum SpanStatusCode {
|
|
6
12
|
OK = "OK",
|
|
@@ -16,4 +22,5 @@ export type Span = {
|
|
|
16
22
|
};
|
|
17
23
|
export declare function startSpan(name: string, options?: SpanOptions): Span;
|
|
18
24
|
export declare function trackSpan<T>(name: string, options: SpanOptions, fn: () => T | Promise<T>): T | Promise<T>;
|
|
25
|
+
export declare function discardSpan(spanId: string): void;
|
|
19
26
|
//# sourceMappingURL=trace.d.ts.map
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/trace.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,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,CAiCnE;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,CAuBhB;AAMD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKhD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dreamhorizonorg/pulse-react-native",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Production-grade observability SDK for React Native applications with OpenTelemetry support. Real-time monitoring, error tracking, performance insights, and distributed tracing.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -10,15 +10,22 @@
|
|
|
10
10
|
"types": "./lib/typescript/src/index.d.ts",
|
|
11
11
|
"default": "./lib/module/index.js"
|
|
12
12
|
},
|
|
13
|
-
"./package.json": "./package.json"
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
"./app.plugin.js": "./app.plugin.js"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"pulse-cli": "./scripts/pulse-cli.js"
|
|
14
18
|
},
|
|
15
19
|
"files": [
|
|
16
20
|
"src",
|
|
17
21
|
"lib",
|
|
22
|
+
"scripts",
|
|
18
23
|
"android",
|
|
19
24
|
"ios",
|
|
20
25
|
"cpp",
|
|
21
26
|
"*.podspec",
|
|
27
|
+
"*.plugin.js",
|
|
28
|
+
"plugin/build",
|
|
22
29
|
"react-native.config.js",
|
|
23
30
|
"!ios/build",
|
|
24
31
|
"!android/build",
|
|
@@ -36,9 +43,11 @@
|
|
|
36
43
|
"test": "jest",
|
|
37
44
|
"typecheck": "tsc",
|
|
38
45
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
39
|
-
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
46
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib plugin/build",
|
|
47
|
+
"build:plugin": "tsc -p plugin/tsconfig.json",
|
|
48
|
+
"prepare": "npm run build:plugin && bob build",
|
|
49
|
+
"release": "release-it --only-version",
|
|
50
|
+
"pulse-cli": "node scripts/pulse-cli.js"
|
|
42
51
|
},
|
|
43
52
|
"keywords": [
|
|
44
53
|
"react-native",
|
|
@@ -72,6 +81,7 @@
|
|
|
72
81
|
"@eslint/eslintrc": "^3.3.1",
|
|
73
82
|
"@eslint/js": "^9.35.0",
|
|
74
83
|
"@evilmartians/lefthook": "^1.12.3",
|
|
84
|
+
"@expo/config-plugins": "^54.0.0",
|
|
75
85
|
"@react-native-community/cli": "20.0.1",
|
|
76
86
|
"@react-native/babel-preset": "0.81.1",
|
|
77
87
|
"@react-native/eslint-config": "^0.81.1",
|
|
@@ -82,7 +92,9 @@
|
|
|
82
92
|
"del-cli": "^6.0.0",
|
|
83
93
|
"eslint": "^9.35.0",
|
|
84
94
|
"eslint-config-prettier": "^10.1.8",
|
|
95
|
+
"eslint-plugin-jest": "^29.11.0",
|
|
85
96
|
"eslint-plugin-prettier": "^5.5.4",
|
|
97
|
+
"expo-module-scripts": "^5.0.8",
|
|
86
98
|
"jest": "^29.7.0",
|
|
87
99
|
"prettier": "^3.6.2",
|
|
88
100
|
"react": "19.1.0",
|
|
@@ -92,10 +104,6 @@
|
|
|
92
104
|
"turbo": "^2.5.6",
|
|
93
105
|
"typescript": "^5.9.2"
|
|
94
106
|
},
|
|
95
|
-
"peerDependencies": {
|
|
96
|
-
"react": "*",
|
|
97
|
-
"react-native": "*"
|
|
98
|
-
},
|
|
99
107
|
"workspaces": [
|
|
100
108
|
"example"
|
|
101
109
|
],
|
|
@@ -161,5 +169,17 @@
|
|
|
161
169
|
"languages": "kotlin-objc",
|
|
162
170
|
"type": "turbo-module",
|
|
163
171
|
"version": "0.54.8"
|
|
172
|
+
},
|
|
173
|
+
"dependencies": {
|
|
174
|
+
"commander": "^14.0.2"
|
|
175
|
+
},
|
|
176
|
+
"engines": {
|
|
177
|
+
"node": ">=18.0.0"
|
|
178
|
+
},
|
|
179
|
+
"app.plugin.js": "./app.plugin.js",
|
|
180
|
+
"peerDependencies": {
|
|
181
|
+
"@expo/config-plugins": "*",
|
|
182
|
+
"react": "*",
|
|
183
|
+
"react-native": "*"
|
|
164
184
|
}
|
|
165
185
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
|
+
const withAndroidPulse_1 = require("./withAndroidPulse");
|
|
5
|
+
const pkg = require('../../package.json');
|
|
6
|
+
const withPulsePlugin = (config, props) => {
|
|
7
|
+
config = (0, withAndroidPulse_1.withAndroidPulse)(config, props);
|
|
8
|
+
return config;
|
|
9
|
+
};
|
|
10
|
+
exports.default = (0, config_plugins_1.createRunOncePlugin)(withPulsePlugin, pkg.name, pkg.version);
|
|
@@ -0,0 +1,26 @@
|
|
|
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 | null>;
|
|
8
|
+
interface IInteractionConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
url?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface PulsePluginProps {
|
|
13
|
+
endpointBaseUrl: string;
|
|
14
|
+
endpointHeaders?: Record<string, string>;
|
|
15
|
+
globalAttributes?: PulseAttributes;
|
|
16
|
+
instrumentation?: {
|
|
17
|
+
interaction?: IInteractionConfig;
|
|
18
|
+
activity?: boolean;
|
|
19
|
+
network?: boolean;
|
|
20
|
+
anr?: boolean;
|
|
21
|
+
crash?: boolean;
|
|
22
|
+
slowRendering?: boolean;
|
|
23
|
+
fragment?: boolean;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const PULSE_IMPORT = "import com.pulsereactnativeotel.Pulse\n";
|
|
2
|
+
export declare const ATTRIBUTES_IMPORT = "import io.opentelemetry.api.common.Attributes\nimport io.opentelemetry.api.common.AttributeKey\n";
|
|
3
|
+
import type { PulsePluginProps } from './types';
|
|
4
|
+
export declare function buildPulseInitializationCode(options: {
|
|
5
|
+
endpointBaseUrl: string;
|
|
6
|
+
endpointHeaders?: Record<string, string>;
|
|
7
|
+
globalAttributes?: PulsePluginProps['globalAttributes'];
|
|
8
|
+
instrumentation?: PulsePluginProps['instrumentation'];
|
|
9
|
+
}): string;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ATTRIBUTES_IMPORT = exports.PULSE_IMPORT = void 0;
|
|
4
|
+
exports.buildPulseInitializationCode = buildPulseInitializationCode;
|
|
5
|
+
exports.PULSE_IMPORT = 'import com.pulsereactnativeotel.Pulse\n';
|
|
6
|
+
exports.ATTRIBUTES_IMPORT = 'import io.opentelemetry.api.common.Attributes\nimport io.opentelemetry.api.common.AttributeKey\n';
|
|
7
|
+
function buildEndpointHeadersMap(headers) {
|
|
8
|
+
const entries = Object.entries(headers).map(([k, v]) => {
|
|
9
|
+
return '"' + k + '" to "' + v + '"';
|
|
10
|
+
});
|
|
11
|
+
return `mapOf(${entries.join(', ')})`;
|
|
12
|
+
}
|
|
13
|
+
function buildGlobalAttributesLambda(attributes) {
|
|
14
|
+
const puts = [];
|
|
15
|
+
Object.entries(attributes)
|
|
16
|
+
.filter(([, value]) => {
|
|
17
|
+
if (value === null || value === undefined)
|
|
18
|
+
return false;
|
|
19
|
+
if (typeof value === 'string' && value === '')
|
|
20
|
+
return false;
|
|
21
|
+
if (Array.isArray(value) && value.length === 0)
|
|
22
|
+
return false;
|
|
23
|
+
return true;
|
|
24
|
+
})
|
|
25
|
+
.forEach(([k, v]) => {
|
|
26
|
+
if (typeof v === 'string') {
|
|
27
|
+
puts.push(`put(AttributeKey.stringKey("${k}"), "${v}")`);
|
|
28
|
+
}
|
|
29
|
+
else if (typeof v === 'number') {
|
|
30
|
+
puts.push(`put(AttributeKey.${Number.isInteger(v) ? 'long' : 'double'}Key("${k}"), ${v}${Number.isInteger(v) ? 'L' : ''})`);
|
|
31
|
+
}
|
|
32
|
+
else if (typeof v === 'boolean') {
|
|
33
|
+
puts.push(`put(AttributeKey.booleanKey("${k}"), ${v})`);
|
|
34
|
+
}
|
|
35
|
+
else if (Array.isArray(v)) {
|
|
36
|
+
const first = v[0];
|
|
37
|
+
if (typeof first === 'string') {
|
|
38
|
+
puts.push(`put(AttributeKey.stringArrayKey("${k}"), listOf(${v.map((x) => `"${x}"`).join(', ')}))`);
|
|
39
|
+
}
|
|
40
|
+
else if (typeof first === 'number') {
|
|
41
|
+
const allInts = v.every((x) => Number.isInteger(x));
|
|
42
|
+
const values = allInts
|
|
43
|
+
? v.map((x) => `${x}L`).join(', ')
|
|
44
|
+
: v
|
|
45
|
+
.map((x) => (Number.isInteger(x) ? `${x}.0` : `${x}`))
|
|
46
|
+
.join(', ');
|
|
47
|
+
puts.push(`put(AttributeKey.${allInts ? 'long' : 'double'}ArrayKey("${k}"), listOf(${values}))`);
|
|
48
|
+
}
|
|
49
|
+
else if (typeof first === 'boolean') {
|
|
50
|
+
puts.push(`put(AttributeKey.booleanArrayKey("${k}"), listOf(${v.join(', ')}))`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
if (puts.length === 0)
|
|
55
|
+
return 'null';
|
|
56
|
+
const formatted = puts
|
|
57
|
+
.map((put) => ` ${put}`)
|
|
58
|
+
.join('\n');
|
|
59
|
+
return `{\n Attributes.builder().apply {\n${formatted}\n }.build()\n }`;
|
|
60
|
+
}
|
|
61
|
+
function buildPulseInitializationCode(options) {
|
|
62
|
+
const { endpointBaseUrl, endpointHeaders, globalAttributes, instrumentation, } = options;
|
|
63
|
+
const params = [];
|
|
64
|
+
if (endpointHeaders && Object.keys(endpointHeaders).length > 0) {
|
|
65
|
+
params.push(`endpointHeaders = ${buildEndpointHeadersMap(endpointHeaders)}`);
|
|
66
|
+
}
|
|
67
|
+
const attributesLambda = globalAttributes
|
|
68
|
+
? buildGlobalAttributesLambda(globalAttributes)
|
|
69
|
+
: null;
|
|
70
|
+
if (attributesLambda && attributesLambda !== 'null') {
|
|
71
|
+
params.push(`globalAttributes = ${attributesLambda}`);
|
|
72
|
+
}
|
|
73
|
+
let code = `\n Pulse.initialize(\n this,\n "${endpointBaseUrl}"${params.length > 0 ? `,\n ${params.join(',\n ')}` : ''}\n ) {\n`;
|
|
74
|
+
if (instrumentation?.interaction !== undefined) {
|
|
75
|
+
if (instrumentation.interaction.url) {
|
|
76
|
+
code += ` interaction { enabled(${instrumentation.interaction.enabled}); setConfigUrl { "${instrumentation.interaction.url}" } }\n`;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
code += ` interaction { enabled(${instrumentation.interaction.enabled}) }\n`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (instrumentation?.activity !== undefined) {
|
|
83
|
+
code += ` activity { enabled(${instrumentation.activity}) }\n`;
|
|
84
|
+
}
|
|
85
|
+
if (instrumentation?.network !== undefined) {
|
|
86
|
+
code += ` networkMonitoring { enabled(${instrumentation.network}) }\n`;
|
|
87
|
+
}
|
|
88
|
+
if (instrumentation?.anr !== undefined) {
|
|
89
|
+
code += ` anrReporter { enabled(${instrumentation.anr}) }\n`;
|
|
90
|
+
}
|
|
91
|
+
if (instrumentation?.slowRendering !== undefined) {
|
|
92
|
+
code += ` slowRenderingReporter { enabled(${instrumentation.slowRendering}) }\n`;
|
|
93
|
+
}
|
|
94
|
+
if (instrumentation?.fragment !== undefined) {
|
|
95
|
+
code += ` fragment { enabled(${instrumentation.fragment}) }\n`;
|
|
96
|
+
}
|
|
97
|
+
if (instrumentation?.crash !== undefined) {
|
|
98
|
+
code += ` crashReporter { enabled(${instrumentation.crash}) }\n`;
|
|
99
|
+
}
|
|
100
|
+
code += ' }\n';
|
|
101
|
+
return code;
|
|
102
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withAndroidPulse = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const withAndroidPulse = (config, props) => {
|
|
8
|
+
return (0, config_plugins_1.withMainApplication)(config, (modConfig) => {
|
|
9
|
+
try {
|
|
10
|
+
const { endpointBaseUrl, endpointHeaders, globalAttributes, instrumentation, } = props;
|
|
11
|
+
// 1. Add import statements
|
|
12
|
+
modConfig.modResults.contents = (0, generateCode_1.mergeContents)({
|
|
13
|
+
src: modConfig.modResults.contents,
|
|
14
|
+
newSrc: utils_1.PULSE_IMPORT,
|
|
15
|
+
tag: 'pulse-sdk-import',
|
|
16
|
+
comment: '//',
|
|
17
|
+
anchor: /import\s+com\.facebook\.react\.ReactApplication/,
|
|
18
|
+
offset: 1,
|
|
19
|
+
}).contents;
|
|
20
|
+
if (globalAttributes && Object.keys(globalAttributes).length > 0) {
|
|
21
|
+
modConfig.modResults.contents = (0, generateCode_1.mergeContents)({
|
|
22
|
+
src: modConfig.modResults.contents,
|
|
23
|
+
newSrc: utils_1.ATTRIBUTES_IMPORT,
|
|
24
|
+
tag: 'pulse-attributes-import',
|
|
25
|
+
comment: '//',
|
|
26
|
+
anchor: /import\s+com\.pulsereactnativeotel\.Pulse/,
|
|
27
|
+
offset: 1,
|
|
28
|
+
}).contents;
|
|
29
|
+
}
|
|
30
|
+
const initCode = (0, utils_1.buildPulseInitializationCode)({
|
|
31
|
+
endpointBaseUrl,
|
|
32
|
+
endpointHeaders,
|
|
33
|
+
globalAttributes,
|
|
34
|
+
instrumentation,
|
|
35
|
+
});
|
|
36
|
+
// 2. Add initialization code after super.onCreate()
|
|
37
|
+
modConfig.modResults.contents = (0, generateCode_1.mergeContents)({
|
|
38
|
+
src: modConfig.modResults.contents,
|
|
39
|
+
newSrc: initCode,
|
|
40
|
+
tag: 'pulse-sdk-initialization',
|
|
41
|
+
comment: '//',
|
|
42
|
+
anchor: /super\.onCreate\(\)/,
|
|
43
|
+
offset: 1,
|
|
44
|
+
}).contents;
|
|
45
|
+
return modConfig;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error('Error modifying MainApplication:', error);
|
|
49
|
+
return modConfig;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
exports.withAndroidPulse = withAndroidPulse;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { checkAndAssertNodeVersion } = require('./utils');
|
|
4
|
+
checkAndAssertNodeVersion();
|
|
5
|
+
|
|
6
|
+
const { Command } = require('commander');
|
|
7
|
+
const { upload } = require('./uploadService');
|
|
8
|
+
const TAG_OPTIONAL = '(OPTIONAL)';
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
|
|
12
|
+
program
|
|
13
|
+
.name('pulse-cli')
|
|
14
|
+
.description('Pulse CLI - Command-line tool for Pulse SDK')
|
|
15
|
+
.usage('[command] [subcommand] [options]')
|
|
16
|
+
.version(require('../package.json').version);
|
|
17
|
+
|
|
18
|
+
const uploadCommand = new Command('upload')
|
|
19
|
+
.description(
|
|
20
|
+
'Upload multiple symbol files to deobfuscate stack traces and improve error debugging.'
|
|
21
|
+
)
|
|
22
|
+
.usage('[subcommand] [options]');
|
|
23
|
+
|
|
24
|
+
uploadCommand
|
|
25
|
+
.command('react-native-android')
|
|
26
|
+
.description('Upload React Native Android files')
|
|
27
|
+
.requiredOption(
|
|
28
|
+
'-u, --api-url <url>',
|
|
29
|
+
'URL for uploading source maps and related build artifacts.'
|
|
30
|
+
)
|
|
31
|
+
.requiredOption(
|
|
32
|
+
'-v, --app-version <version>',
|
|
33
|
+
'App version of the application (e.g., 1.0.0)'
|
|
34
|
+
)
|
|
35
|
+
.requiredOption('-c, --version-code <code>', 'Version code (e.g., 1)')
|
|
36
|
+
.requiredOption(
|
|
37
|
+
'-j, --js-sourcemap <path>',
|
|
38
|
+
'JavaScript source map file path'
|
|
39
|
+
)
|
|
40
|
+
.option(
|
|
41
|
+
'-b, --bundle-id <id>',
|
|
42
|
+
`${TAG_OPTIONAL} CodePush bundle label for identifying the specific bundle version (e.g., v1)`
|
|
43
|
+
)
|
|
44
|
+
.option(
|
|
45
|
+
'-m, --mapping <path>',
|
|
46
|
+
`${TAG_OPTIONAL} ProGuard/R8 mapping file path`
|
|
47
|
+
)
|
|
48
|
+
.option('-d, --debug', `${TAG_OPTIONAL} Show debug information`)
|
|
49
|
+
.action(async (options) => {
|
|
50
|
+
await upload('react-native-android', options);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
uploadCommand
|
|
54
|
+
.command('react-native-ios')
|
|
55
|
+
.description('Upload React Native iOS source maps')
|
|
56
|
+
.requiredOption(
|
|
57
|
+
'-u, --api-url <url>',
|
|
58
|
+
'URL for uploading source maps and related build artifacts.'
|
|
59
|
+
)
|
|
60
|
+
.requiredOption(
|
|
61
|
+
'-v, --bundle-version <version>',
|
|
62
|
+
'Bundle version from Info.plist CFBundleShortVersionString (e.g., 1.0.0)'
|
|
63
|
+
)
|
|
64
|
+
.requiredOption('-c, --version-code <code>', 'Version code (e.g., 1)')
|
|
65
|
+
.requiredOption(
|
|
66
|
+
'-j, --js-sourcemap <path>',
|
|
67
|
+
'JavaScript source map file path'
|
|
68
|
+
)
|
|
69
|
+
.option(
|
|
70
|
+
'-b, --bundle-id <id>',
|
|
71
|
+
`${TAG_OPTIONAL} CodePush bundle label for identifying the specific bundle version (e.g., v1)`
|
|
72
|
+
)
|
|
73
|
+
.option('-d, --debug', `${TAG_OPTIONAL} Show debug information`)
|
|
74
|
+
.action(async (options) => {
|
|
75
|
+
await upload('react-native-ios', options);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
program.addCommand(uploadCommand);
|
|
79
|
+
|
|
80
|
+
program.showHelpAfterError();
|
|
81
|
+
|
|
82
|
+
program.parse();
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/* global Buffer */
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const {
|
|
4
|
+
getPlatform,
|
|
5
|
+
validateFiles,
|
|
6
|
+
validateVersionVersionCodeBundleId,
|
|
7
|
+
} = require('./utils');
|
|
8
|
+
|
|
9
|
+
function buildMetadata(files, appVersion, versionCode, platform, bundleId) {
|
|
10
|
+
const metadata = files.map((file) => ({
|
|
11
|
+
type: file.metadataType,
|
|
12
|
+
appVersion: appVersion,
|
|
13
|
+
versionCode: versionCode,
|
|
14
|
+
platform: platform,
|
|
15
|
+
fileName: file.fileName,
|
|
16
|
+
bundleId: bundleId || null,
|
|
17
|
+
}));
|
|
18
|
+
return metadata;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function uploadFiles(commandName, options) {
|
|
22
|
+
const platform = getPlatform(commandName);
|
|
23
|
+
const files = validateFiles(options);
|
|
24
|
+
const version =
|
|
25
|
+
platform === 'ios' ? options.bundleVersion : options.appVersion;
|
|
26
|
+
|
|
27
|
+
const metadata = buildMetadata(
|
|
28
|
+
files,
|
|
29
|
+
version,
|
|
30
|
+
options.versionCode,
|
|
31
|
+
platform,
|
|
32
|
+
options.bundleId
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const formData = new FormData();
|
|
36
|
+
const metadataContent = JSON.stringify(metadata, null, 2);
|
|
37
|
+
|
|
38
|
+
if (options.debug) {
|
|
39
|
+
console.log('\nš Metadata content (metadata.txt):');
|
|
40
|
+
console.log('ā'.repeat(60));
|
|
41
|
+
console.log(metadataContent);
|
|
42
|
+
console.log('ā'.repeat(60));
|
|
43
|
+
console.log(
|
|
44
|
+
`Metadata size: ${Buffer.byteLength(metadataContent, 'utf-8')} bytes\n`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const metadataBlob = new Blob([metadataContent], {
|
|
49
|
+
type: 'application/json',
|
|
50
|
+
});
|
|
51
|
+
formData.append('metadata', metadataBlob, 'metadata.txt');
|
|
52
|
+
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
const fileBuffer = fs.readFileSync(file.path);
|
|
55
|
+
const fileBlob = new Blob([fileBuffer]);
|
|
56
|
+
formData.append('fileContent', fileBlob, file.fileName);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log(`\nš¤ Uploading ${files.length} file(s) to ${options.apiUrl}...`);
|
|
60
|
+
console.log(` Command: ${commandName}`);
|
|
61
|
+
console.log(` Platform: ${platform}`);
|
|
62
|
+
files.forEach((file) => {
|
|
63
|
+
console.log(` - ${file.fileName} (${file.metadataType})`);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (options.debug) {
|
|
67
|
+
console.log('\nš Debug Info:');
|
|
68
|
+
console.log(` API URL: ${options.apiUrl}`);
|
|
69
|
+
console.log(` App Version: ${version}`);
|
|
70
|
+
console.log(` Version Code: ${options.versionCode}`);
|
|
71
|
+
if (options.bundleId) {
|
|
72
|
+
console.log(` Bundle ID: ${options.bundleId}`);
|
|
73
|
+
}
|
|
74
|
+
files.forEach((file) => {
|
|
75
|
+
const stats = fs.statSync(file.path);
|
|
76
|
+
console.log(
|
|
77
|
+
` File: ${file.fileName} (${(stats.size / 1024).toFixed(2)} KB)`
|
|
78
|
+
);
|
|
79
|
+
console.log(` File Path: ${file.path}`);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const response = await fetch(options.apiUrl, {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
body: formData,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const responseData = await response.json().catch(async () => {
|
|
89
|
+
const text = await response.text();
|
|
90
|
+
return text ? { message: text } : {};
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (options.debug && responseData && Object.keys(responseData).length > 0) {
|
|
94
|
+
console.log('\nš„ Backend Response:');
|
|
95
|
+
console.log(` Status: ${response.status} ${response.statusText}`);
|
|
96
|
+
console.log(` Response: ${JSON.stringify(responseData, null, 2)}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const errorText =
|
|
101
|
+
responseData.error || responseData.message || 'Unknown error';
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Upload failed: HTTP ${response.status} ${response.statusText}. ${errorText}`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log('\nā Files uploaded successfully');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function upload(commandName, options) {
|
|
111
|
+
try {
|
|
112
|
+
validateVersionVersionCodeBundleId(options, commandName);
|
|
113
|
+
await uploadFiles(commandName, options);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(`\nā Error: ${error.message}`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = {
|
|
121
|
+
upload,
|
|
122
|
+
};
|