@bytem/bytem-tracker-app 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.
- package/README.md +41 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.js +3 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/tracker.d.ts +26 -0
- package/dist/tracker.js +96 -0
- package/dist/types.d.ts +24 -0
- package/dist/types.js +1 -0
- package/dist/uuid.d.ts +1 -0
- package/dist/uuid.js +16 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @bytem/bytem-tracker
|
|
2
|
+
|
|
3
|
+
ByteM 埋点 SDK(React Native / Expo)
|
|
4
|
+
|
|
5
|
+
> 本 SDK 为 Flutter `bytem_tracker.dart` 的 **1:1 行为迁移版本**
|
|
6
|
+
> 字段、默认值、payload 结构完全一致,后端无需任何改动
|
|
7
|
+
|
|
8
|
+
### 此项目运行起来
|
|
9
|
+
```bash
|
|
10
|
+
rm -rf dist
|
|
11
|
+
yarn install
|
|
12
|
+
yarn build
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ✨ 特性
|
|
18
|
+
|
|
19
|
+
- ✅ React Native / Expo 通用
|
|
20
|
+
- ✅ 行为 100% 对齐 Flutter SDK
|
|
21
|
+
- ✅ 单例模式
|
|
22
|
+
- ✅ 自动 deviceId / visitorId 管理
|
|
23
|
+
- ✅ TypeScript 支持
|
|
24
|
+
- ❌ 不支持 Web(刻意限制,避免误用)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 📦 安装
|
|
29
|
+
|
|
30
|
+
### React Native CLI
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
yarn add @bytem/bytem-tracker
|
|
34
|
+
yarn add @react-native-async-storage/async-storage
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Expo
|
|
38
|
+
```bash
|
|
39
|
+
expo install @react-native-async-storage/async-storage
|
|
40
|
+
yarn add @bytem/bytem-tracker
|
|
41
|
+
```
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isExpoRuntime(): boolean;
|
package/dist/env.js
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare class BytemTracker {
|
|
2
|
+
private static _instance;
|
|
3
|
+
static get instance(): BytemTracker;
|
|
4
|
+
private static readonly _sdkName;
|
|
5
|
+
private static readonly _sdkVersion;
|
|
6
|
+
private static readonly _defaultBaseUrl;
|
|
7
|
+
private static readonly _storageDeviceIdKey;
|
|
8
|
+
private static readonly _storageVisitorIdKey;
|
|
9
|
+
private _appKey;
|
|
10
|
+
private _baseUrl;
|
|
11
|
+
private _debug;
|
|
12
|
+
private _deviceId;
|
|
13
|
+
private _visitorId;
|
|
14
|
+
private constructor();
|
|
15
|
+
init(options: {
|
|
16
|
+
appKey: string;
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
deviceId?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
track(eventKey: string, params?: Record<string, any>): Promise<void>;
|
|
22
|
+
private _loadOrCreateDeviceId;
|
|
23
|
+
private _loadOrCreateVisitorId;
|
|
24
|
+
private _getScreenInfo;
|
|
25
|
+
private _log;
|
|
26
|
+
}
|
package/dist/tracker.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
+
import { Dimensions, Platform } from 'react-native';
|
|
3
|
+
import { generateUUID } from './uuid';
|
|
4
|
+
export class BytemTracker {
|
|
5
|
+
static get instance() {
|
|
6
|
+
if (!this._instance) {
|
|
7
|
+
this._instance = new BytemTracker();
|
|
8
|
+
}
|
|
9
|
+
return this._instance;
|
|
10
|
+
}
|
|
11
|
+
constructor() {
|
|
12
|
+
this._appKey = null;
|
|
13
|
+
this._baseUrl = BytemTracker._defaultBaseUrl;
|
|
14
|
+
this._debug = false;
|
|
15
|
+
this._deviceId = null;
|
|
16
|
+
this._visitorId = null;
|
|
17
|
+
}
|
|
18
|
+
async init(options) {
|
|
19
|
+
var _a;
|
|
20
|
+
this._appKey = options.appKey;
|
|
21
|
+
this._debug = (_a = options.debug) !== null && _a !== void 0 ? _a : false;
|
|
22
|
+
if (options.baseUrl) {
|
|
23
|
+
this._baseUrl = options.baseUrl;
|
|
24
|
+
}
|
|
25
|
+
if (options.deviceId) {
|
|
26
|
+
this._deviceId = options.deviceId;
|
|
27
|
+
await AsyncStorage.setItem(BytemTracker._storageDeviceIdKey, this._deviceId);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
await this._loadOrCreateDeviceId();
|
|
31
|
+
}
|
|
32
|
+
await this._loadOrCreateVisitorId();
|
|
33
|
+
this._log('init', {
|
|
34
|
+
deviceId: this._deviceId,
|
|
35
|
+
visitorId: this._visitorId,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async track(eventKey, params = {}) {
|
|
39
|
+
if (!this._appKey || !this._deviceId || !this._visitorId) {
|
|
40
|
+
this._log('track skipped: not initialized');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const payload = {
|
|
44
|
+
app_key: this._appKey,
|
|
45
|
+
device_id: this._deviceId,
|
|
46
|
+
visitor_id: this._visitorId,
|
|
47
|
+
event_key: eventKey,
|
|
48
|
+
params,
|
|
49
|
+
sdk: BytemTracker._sdkName,
|
|
50
|
+
sdk_version: BytemTracker._sdkVersion,
|
|
51
|
+
platform: Platform.OS,
|
|
52
|
+
timestamp: Date.now(),
|
|
53
|
+
screen: this._getScreenInfo(),
|
|
54
|
+
};
|
|
55
|
+
this._log('track', payload);
|
|
56
|
+
try {
|
|
57
|
+
await fetch(`${this._baseUrl}/track`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { 'Content-Type': 'application/json' },
|
|
60
|
+
body: JSON.stringify(payload),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
this._log('track error', e);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async _loadOrCreateDeviceId() {
|
|
68
|
+
const stored = await AsyncStorage.getItem(BytemTracker._storageDeviceIdKey);
|
|
69
|
+
this._deviceId = stored !== null && stored !== void 0 ? stored : generateUUID();
|
|
70
|
+
if (!stored && this._deviceId) {
|
|
71
|
+
await AsyncStorage.setItem(BytemTracker._storageDeviceIdKey, this._deviceId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async _loadOrCreateVisitorId() {
|
|
75
|
+
const stored = await AsyncStorage.getItem(BytemTracker._storageVisitorIdKey);
|
|
76
|
+
this._visitorId = stored !== null && stored !== void 0 ? stored : generateUUID();
|
|
77
|
+
if (!stored && this._visitorId) {
|
|
78
|
+
await AsyncStorage.setItem(BytemTracker._storageVisitorIdKey, this._visitorId);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
_getScreenInfo() {
|
|
82
|
+
const { width, height } = Dimensions.get('window');
|
|
83
|
+
return { width, height };
|
|
84
|
+
}
|
|
85
|
+
_log(...args) {
|
|
86
|
+
if (this._debug) {
|
|
87
|
+
console.log('[BytemTracker]', ...args);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
BytemTracker._instance = null;
|
|
92
|
+
BytemTracker._sdkName = 'bytemTrackerReact';
|
|
93
|
+
BytemTracker._sdkVersion = '0.0.1';
|
|
94
|
+
BytemTracker._defaultBaseUrl = 'https://tracking.server.bytecon.com';
|
|
95
|
+
BytemTracker._storageDeviceIdKey = 'bytem_fp';
|
|
96
|
+
BytemTracker._storageVisitorIdKey = 'bytem_visitor_id';
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** SDK 初始化配置 */
|
|
2
|
+
export interface BytemConfig {
|
|
3
|
+
appKey: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
debug?: boolean;
|
|
6
|
+
visitorId?: string;
|
|
7
|
+
appScheme?: string;
|
|
8
|
+
}
|
|
9
|
+
/** 基础事件可选参数 */
|
|
10
|
+
export interface BytemEventOptions {
|
|
11
|
+
count?: number;
|
|
12
|
+
sum?: number;
|
|
13
|
+
duration?: number;
|
|
14
|
+
}
|
|
15
|
+
/** 用户资料参数 */
|
|
16
|
+
export interface BytemUserParams {
|
|
17
|
+
userId?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
email?: string;
|
|
20
|
+
phone?: string;
|
|
21
|
+
gender?: "M" | "F";
|
|
22
|
+
birthYear?: number;
|
|
23
|
+
custom?: Record<string, any>;
|
|
24
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateUUID(): string;
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
function jsUUIDv4() {
|
|
3
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
4
|
+
const r = (Math.random() * 16) | 0;
|
|
5
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
6
|
+
return v.toString(16);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export function generateUUID() {
|
|
10
|
+
try {
|
|
11
|
+
return uuidv4();
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return jsUUIDv4();
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bytem/bytem-tracker-app",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"files": ["dist"],
|
|
7
|
+
"description": "bytem SDK for React Native",
|
|
8
|
+
"license": "ISC",
|
|
9
|
+
"author": "Barry",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepublishOnly": "npm run build",
|
|
13
|
+
"publish": "npm publish"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"react-native": ">=0.60.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@react-native-async-storage/async-storage": "^1.21.0",
|
|
20
|
+
"uuid": "^9.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/react-native": "^0.73.0",
|
|
24
|
+
"@types/uuid": "^9.0.0",
|
|
25
|
+
"typescript": "^5.0.0"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"registry": "https://registry.npmjs.org"
|
|
30
|
+
},
|
|
31
|
+
"volta": {
|
|
32
|
+
"node": "22.12.0",
|
|
33
|
+
"yarn": "1.22.21"
|
|
34
|
+
}
|
|
35
|
+
}
|