@amplytools/react-native-amply-sdk 0.1.0 → 0.1.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.
@@ -68,6 +68,14 @@ namespace facebook::react {
68
68
  return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "registerDeepLinkListener", @selector(registerDeepLinkListener), args, count);
69
69
  }
70
70
 
71
+ static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_setLogLevel(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
72
+ return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "setLogLevel", @selector(setLogLevel:), args, count);
73
+ }
74
+
75
+ static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_getLogLevel(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
76
+ return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, StringKind, "getLogLevel", @selector(getLogLevel), args, count);
77
+ }
78
+
71
79
  static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
72
80
  return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count);
73
81
  }
@@ -95,8 +103,14 @@ namespace facebook::react {
95
103
 
96
104
 
97
105
  methodMap_["registerDeepLinkListener"] = MethodMetadata {0, __hostFunction_NativeAmplyModuleSpecJSI_registerDeepLinkListener};
98
-
99
-
106
+
107
+
108
+ methodMap_["setLogLevel"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_setLogLevel};
109
+
110
+
111
+ methodMap_["getLogLevel"] = MethodMetadata {0, __hostFunction_NativeAmplyModuleSpecJSI_getLogLevel};
112
+
113
+
100
114
  methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_addListener};
101
115
 
102
116
 
@@ -41,6 +41,8 @@ namespace JS {
41
41
  NSString *endpoint() const;
42
42
  id<NSObject> _Nullable datasetPrefetch() const;
43
43
  NSString *defaultConfig() const;
44
+ std::optional<bool> debug() const;
45
+ NSString *logLevel() const;
44
46
 
45
47
  AmplyInitializationConfig(NSDictionary *const v) : _v(v) {}
46
48
  private:
@@ -84,6 +86,8 @@ namespace JS {
84
86
  resolve:(RCTPromiseResolveBlock)resolve
85
87
  reject:(RCTPromiseRejectBlock)reject;
86
88
  - (void)registerDeepLinkListener;
89
+ - (void)setLogLevel:(NSString *)level;
90
+ - (NSString *)getLogLevel;
87
91
  - (void)addListener:(NSString *)eventName;
88
92
  - (void)removeListeners:(double)count;
89
93
 
@@ -138,6 +142,16 @@ inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::defaultConfig
138
142
  id const p = _v[@"defaultConfig"];
139
143
  return RCTBridgingToOptionalString(p);
140
144
  }
145
+ inline std::optional<bool> JS::NativeAmplyModule::AmplyInitializationConfig::debug() const
146
+ {
147
+ id const p = _v[@"debug"];
148
+ return RCTBridgingToOptionalBool(p);
149
+ }
150
+ inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::logLevel() const
151
+ {
152
+ id const p = _v[@"logLevel"];
153
+ return RCTBridgingToOptionalString(p);
154
+ }
141
155
  inline NSString *JS::NativeAmplyModule::TrackEventPayload::name() const
142
156
  {
143
157
  id const p = _v[@"name"];
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@amplytools/react-native-amply-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "React Native SDK for Amply: Mobile SDK to orchestrate in-app experiences and campaigns remotely, without app releases",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/amply/amply-react-native.git"
8
+ "url": "https://github.com/amply-tools/amply-react-native.git"
9
9
  },
10
- "homepage": "https://github.com/amply/amply-react-native",
10
+ "homepage": "https://github.com/amply-tools/amply-react-native#readme",
11
11
  "bugs": {
12
- "url": "https://github.com/amply/amply-react-native/issues"
12
+ "url": "https://github.com/amply-tools/amply-react-native/issues"
13
13
  },
14
14
  "main": "dist/index.js",
15
15
  "module": "dist/index.mjs",
@@ -18,9 +18,6 @@
18
18
  "source": "src/index.ts",
19
19
  "files": [
20
20
  "android/",
21
- "!android/.cxx/",
22
- "!android/build/",
23
- "!android/.gradle/",
24
21
  "ios/",
25
22
  "dist/",
26
23
  "src/",
@@ -46,6 +43,8 @@
46
43
  "react-native": ">=0.79.0"
47
44
  },
48
45
  "devDependencies": {
46
+ "@babel/core": "^7.28.6",
47
+ "@babel/preset-flow": "^7.27.1",
49
48
  "@react-native/codegen": "0.81.4",
50
49
  "@react-native/eslint-config": "^0.74.81",
51
50
  "@react-native/typescript-config": "0.81.0",
@@ -57,6 +56,7 @@
57
56
  "expo": "^54.0.0",
58
57
  "expo-module-scripts": "^3.5.0",
59
58
  "jest": "^29.7.0",
59
+ "metro-react-native-babel-preset": "^0.77.0",
60
60
  "typescript": "^5.4.0"
61
61
  },
62
62
  "engines": {
package/src/index.ts CHANGED
@@ -2,18 +2,69 @@ import getNativeModule from './nativeModule';
2
2
  import {addSystemEventListener as addSystemEventListenerInternal} from './systemEvents';
3
3
  export {useAmplySystemEvents} from './hooks/useAmplySystemEvents';
4
4
  export {formatSystemEventLabel} from './systemEventUtils';
5
+ export type {FormatOptions} from './systemEventUtils';
5
6
  import type {
6
7
  AmplyInitializationConfig,
7
8
  DataSetSnapshot,
8
9
  DataSetType,
9
10
  DeepLinkEvent,
10
11
  EventRecord,
12
+ LogLevel,
11
13
  TrackEventPayload,
12
14
  } from './nativeSpecs/NativeAmplyModule';
13
15
 
14
16
  let deepLinkRegistered = false;
17
+ let debugLogListenerRegistered = false;
15
18
  const deepLinkSubscriptions = new Set<() => void>();
16
19
 
20
+ /**
21
+ * Format a debug log entry for console output.
22
+ */
23
+ function formatDebugLog(event: EventRecord): string {
24
+ const props = event.properties as {
25
+ level?: string;
26
+ category?: string;
27
+ message?: string;
28
+ };
29
+ const level = props.level?.toUpperCase() || 'DEBUG';
30
+ const category = props.category || '';
31
+ return `[Amply ${level}] [${category}] ${props.message || ''}`;
32
+ }
33
+
34
+ /**
35
+ * Set up debug log listener that outputs to console.
36
+ * This is called automatically when debug mode is enabled.
37
+ */
38
+ function ensureDebugLogListener(): void {
39
+ if (debugLogListenerRegistered) {
40
+ return;
41
+ }
42
+ debugLogListenerRegistered = true;
43
+
44
+ addSystemEventListenerInternal((event: EventRecord) => {
45
+ if (event.name === 'DebugLog') {
46
+ const formattedLog = formatDebugLog(event);
47
+ const props = event.properties as {level?: string};
48
+ const level = props.level?.toLowerCase();
49
+
50
+ // Use appropriate console method based on log level
51
+ switch (level) {
52
+ case 'error':
53
+ console.error(formattedLog);
54
+ break;
55
+ case 'warn':
56
+ console.warn(formattedLog);
57
+ break;
58
+ case 'debug':
59
+ console.debug(formattedLog);
60
+ break;
61
+ default:
62
+ console.log(formattedLog);
63
+ }
64
+ }
65
+ });
66
+ }
67
+
17
68
  async function ensureDeepLinkRegistration(): Promise<void> {
18
69
  if (!deepLinkRegistered) {
19
70
  console.log('[Amply] Calling registerDeepLinkListener on native module');
@@ -38,9 +89,34 @@ function trackDeepLinkSubscription(subscription?: {remove?: () => void}): () =>
38
89
  }
39
90
 
40
91
  export async function initialize(config: AmplyInitializationConfig): Promise<void> {
92
+ // Set up debug log listener if debug mode is enabled
93
+ if (config.debug || config.logLevel) {
94
+ ensureDebugLogListener();
95
+ }
96
+
41
97
  await getNativeModule().initialize(config);
42
98
  }
43
99
 
100
+ /**
101
+ * Set the log level at runtime.
102
+ * @param level The log level: 'none' | 'error' | 'warn' | 'info' | 'debug'
103
+ */
104
+ export function setLogLevel(level: LogLevel): void {
105
+ // Ensure debug log listener is set up when changing log level
106
+ if (level !== 'none') {
107
+ ensureDebugLogListener();
108
+ }
109
+ getNativeModule().setLogLevel(level);
110
+ }
111
+
112
+ /**
113
+ * Get the current log level.
114
+ * @returns The current log level
115
+ */
116
+ export function getLogLevel(): LogLevel {
117
+ return getNativeModule().getLogLevel() as LogLevel;
118
+ }
119
+
44
120
  export function isInitialized(): boolean {
45
121
  return getNativeModule().isInitialized();
46
122
  }
@@ -88,6 +164,7 @@ export type {
88
164
  DataSetType,
89
165
  DeepLinkEvent,
90
166
  EventRecord,
167
+ LogLevel,
91
168
  TrackEventPayload,
92
169
  };
93
170
 
@@ -111,5 +188,7 @@ export default {
111
188
  addSystemEventListener,
112
189
  addSystemEventsListener,
113
190
  removeAllListeners,
191
+ setLogLevel,
192
+ getLogLevel,
114
193
  systemEvents,
115
194
  };
@@ -4,6 +4,16 @@ import type {EventEmitter} from 'react-native/Libraries/Types/CodegenTypes';
4
4
 
5
5
  type JsonMap = {[key: string]: unknown};
6
6
 
7
+ /**
8
+ * Log level for SDK debug output.
9
+ * - 'none': No logging
10
+ * - 'error': Only errors
11
+ * - 'warn': Errors and warnings
12
+ * - 'info': SDK lifecycle events (init, session start/end)
13
+ * - 'debug': Everything including campaign evaluation details
14
+ */
15
+ export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
16
+
7
17
  export type AmplyInitializationConfig = {
8
18
  appId: string;
9
19
  apiKeyPublic: string;
@@ -11,6 +21,16 @@ export type AmplyInitializationConfig = {
11
21
  endpoint?: string | null;
12
22
  datasetPrefetch?: DataSetType[] | null;
13
23
  defaultConfig?: string | null;
24
+ /**
25
+ * Enable debug logging. Shorthand for logLevel: 'debug'.
26
+ * When true, logs will appear in the Metro console.
27
+ */
28
+ debug?: boolean | null;
29
+ /**
30
+ * Set the log level for SDK output.
31
+ * Takes precedence over `debug` if both are specified.
32
+ */
33
+ logLevel?: LogLevel | null;
14
34
  };
15
35
 
16
36
  export type EventType = 'custom' | 'system';
@@ -71,6 +91,16 @@ export interface Spec extends TurboModule {
71
91
  getRecentEvents(limit: number): Promise<EventRecord[]>;
72
92
  getDataSetSnapshot(type: DataSetType): Promise<DataSetSnapshot>;
73
93
  registerDeepLinkListener(): void;
94
+ /**
95
+ * Set the log level at runtime.
96
+ * @param level The log level to set
97
+ */
98
+ setLogLevel(level: string): void;
99
+ /**
100
+ * Get the current log level.
101
+ * @returns The current log level as a string
102
+ */
103
+ getLogLevel(): string;
74
104
  readonly onSystemEvent: EventEmitter<SystemEventPayload>;
75
105
  readonly onDeepLink: EventEmitter<DeepLinkEvent>;
76
106
  addListener(eventName: string): void;
@@ -12,7 +12,17 @@ const DEFAULT_LABELS: Record<string, string> = {
12
12
  CampaignFinished: 'Campaign finished',
13
13
  };
14
14
 
15
- export function formatSystemEventLabel(event: EventRecord): string {
15
+ export interface FormatOptions {
16
+ /** When true, includes detailed campaign information. Default: false */
17
+ verbose?: boolean;
18
+ }
19
+
20
+ export function formatSystemEventLabel(
21
+ event: EventRecord,
22
+ options: FormatOptions = {},
23
+ ): string {
24
+ const {verbose = false} = options;
25
+
16
26
  if (event.name === 'CampaignShown') {
17
27
  const campaignId = event.properties.campaignId as string | undefined;
18
28
  const source = event.properties.source as string | undefined;
@@ -27,9 +37,20 @@ export function formatSystemEventLabel(event: EventRecord): string {
27
37
  if (event.name === 'ConfigFetchFinished') {
28
38
  const success = event.properties.success as boolean | undefined;
29
39
  const campaignCount = event.properties.campaignCount as number | undefined;
30
- const countLabel =
31
- typeof campaignCount === 'number' ? ` (${campaignCount} campaigns)` : '';
32
- return success === false ? 'Config fetch failed' : `Config fetch finished${countLabel}`;
40
+ const campaigns = event.properties.campaigns as Array<{id: string; name: string}> | undefined;
41
+
42
+ if (success === false) {
43
+ return 'Config fetch failed';
44
+ }
45
+
46
+ const countLabel = typeof campaignCount === 'number' ? `${campaignCount}` : '0';
47
+
48
+ if (verbose && campaigns && campaigns.length > 0) {
49
+ const campaignLines = campaigns.map(c => `- [${c.id}] ${c.name}`).join('\n');
50
+ return `Config fetch finished\nCampaigns: ${countLabel}\n${campaignLines}`;
51
+ }
52
+
53
+ return `Config fetch finished (${countLabel} campaigns)`;
33
54
  }
34
55
  return DEFAULT_LABELS[event.name] ?? `System event ${event.name}`;
35
56
  }