@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.
- package/README.md +33 -673
- package/android/build.gradle +1 -1
- package/android/src/main/java/tools/amply/sdk/reactnative/AmplyModule.kt +32 -1
- package/android/src/main/java/tools/amply/sdk/reactnative/core/AmplyClient.kt +5 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/core/DefaultAmplyClient.kt +49 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/model/AmplyInitializationOptions.kt +35 -1
- package/dist/src/index.d.ts +15 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +67 -0
- package/dist/src/nativeSpecs/NativeAmplyModule.d.ts +29 -0
- package/dist/src/nativeSpecs/NativeAmplyModule.d.ts.map +1 -1
- package/dist/src/systemEventUtils.d.ts +5 -1
- package/dist/src/systemEventUtils.d.ts.map +1 -1
- package/dist/src/systemEventUtils.js +12 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/DEVELOPMENT.md +177 -0
- package/docs/FEATURE_DEBUG.md +326 -0
- package/ios/AmplyReactNative.podspec +1 -1
- package/ios/Sources/AmplyReactNative/AmplyModule.mm +160 -1
- package/ios/Sources/AmplyReactNative/AmplyReactNative/AmplyReactNative-generated.mm +16 -2
- package/ios/Sources/AmplyReactNative/AmplyReactNative/AmplyReactNative.h +14 -0
- package/package.json +7 -7
- package/src/index.ts +79 -0
- package/src/nativeSpecs/NativeAmplyModule.ts +30 -0
- package/src/systemEventUtils.ts +25 -4
|
@@ -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.
|
|
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;
|
package/src/systemEventUtils.ts
CHANGED
|
@@ -12,7 +12,17 @@ const DEFAULT_LABELS: Record<string, string> = {
|
|
|
12
12
|
CampaignFinished: 'Campaign finished',
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export
|
|
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
|
|
31
|
-
|
|
32
|
-
|
|
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
|
}
|