@norcy/react-native-toolkit 0.1.5 → 0.1.6

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 (37) hide show
  1. package/lib/commonjs/AppleLoginUtil.js +138 -0
  2. package/lib/commonjs/AppleLoginUtil.js.map +1 -0
  3. package/lib/commonjs/PrefData.js +122 -0
  4. package/lib/commonjs/PrefData.js.map +1 -0
  5. package/lib/commonjs/ReportUtil.js +116 -0
  6. package/lib/commonjs/ReportUtil.js.map +1 -0
  7. package/lib/commonjs/SentryManager.js +55 -0
  8. package/lib/commonjs/SentryManager.js.map +1 -0
  9. package/lib/commonjs/constant.js +18 -0
  10. package/lib/commonjs/constant.js.map +1 -0
  11. package/lib/commonjs/index.js +60 -0
  12. package/lib/commonjs/index.js.map +1 -1
  13. package/lib/module/AppleLoginUtil.js +132 -0
  14. package/lib/module/AppleLoginUtil.js.map +1 -0
  15. package/lib/module/PrefData.js +115 -0
  16. package/lib/module/PrefData.js.map +1 -0
  17. package/lib/module/ReportUtil.js +110 -0
  18. package/lib/module/ReportUtil.js.map +1 -0
  19. package/lib/module/SentryManager.js +47 -0
  20. package/lib/module/SentryManager.js.map +1 -0
  21. package/lib/module/constant.js +12 -0
  22. package/lib/module/constant.js.map +1 -0
  23. package/lib/module/index.js +5 -0
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/typescript/AppleLoginUtil.d.ts +27 -0
  26. package/lib/typescript/PrefData.d.ts +15 -0
  27. package/lib/typescript/ReportUtil.d.ts +12 -0
  28. package/lib/typescript/SentryManager.d.ts +5 -0
  29. package/lib/typescript/constant.d.ts +17 -0
  30. package/lib/typescript/index.d.ts +5 -0
  31. package/package.json +13 -3
  32. package/src/AppleLoginUtil.ts +107 -0
  33. package/src/PrefData.ts +134 -0
  34. package/src/ReportUtil.ts +138 -0
  35. package/src/SentryManager.ts +49 -0
  36. package/src/constant.ts +20 -0
  37. package/src/index.tsx +5 -0
@@ -0,0 +1,107 @@
1
+ import { appleAuth } from '@invertase/react-native-apple-authentication';
2
+ import { getBundleId } from 'react-native-device-info';
3
+ import { LoginState } from './constant';
4
+
5
+ const AV = require('leancloud-storage');
6
+
7
+ const AppleLoginUtil = {
8
+ // 这是监听苹果取消授权的回调,目前不需要
9
+ // appleAuth.onCredentialRevoked(async () => {
10
+ // fetchAndUpdateCredentialState(loginUser).catch(error => {
11
+ // updateCredentialStateForUser(`Error: ${error.code}`)
12
+ // });
13
+ // });
14
+
15
+ fetchAndUpdateCredentialState: async (user: string, callback: Function) => {
16
+ console.log('User 正在登录鉴权:', user);
17
+
18
+ if (user === null) {
19
+ callback({ result: LoginState.NOTLOGIN }, { error: 'USER EMPTY' });
20
+ } else {
21
+ const credentialState = await appleAuth.getCredentialStateForUser(user);
22
+ if (credentialState === appleAuth.State.AUTHORIZED) {
23
+ console.log('登录鉴权成功');
24
+ callback({ result: LoginState.AUTHORIZED });
25
+ } else {
26
+ console.warn('登录鉴权失败');
27
+ callback(
28
+ { result: LoginState.NOTLOGIN },
29
+ { error: 'Authorized Failed' }
30
+ );
31
+ }
32
+ }
33
+ },
34
+
35
+ requestAppleUserForLogin: async () => {
36
+ if (!appleAuth.isSupported) {
37
+ return { error: 'Apple Auth Not Supported' };
38
+ }
39
+
40
+ // start a login request
41
+ try {
42
+ const appleAuthRequestResponse = await appleAuth.performRequest({
43
+ requestedOperation: appleAuth.Operation.LOGIN,
44
+ requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
45
+ });
46
+
47
+ console.log('appleAuthRequestResponse login', appleAuthRequestResponse);
48
+
49
+ const { user: newUser, email, identityToken } = appleAuthRequestResponse;
50
+
51
+ console.log(`Apple Authentication Completed, ${newUser}, ${email}`);
52
+
53
+ return { user: newUser, email: email, identityToken: identityToken };
54
+ } catch (error: any) {
55
+ if (error.code === appleAuth.Error.CANCELED) {
56
+ // console.warn('User canceled Apple Sign in.');
57
+ return { error: 'User Cancel Login', code: error.code };
58
+ } else {
59
+ // console.warn('登录鉴权出错: ', error);
60
+ return { error: 'Login Request Fail', code: error.code };
61
+ }
62
+ }
63
+ },
64
+
65
+ requestAppleUserForLogout: async () => {
66
+ if (!appleAuth.isSupported) {
67
+ throw { error: 'Apple Auth Not Supported', code: -1 };
68
+ }
69
+
70
+ // start a login request
71
+ try {
72
+ const appleAuthRequestResponse = await appleAuth.performRequest({
73
+ requestedOperation: appleAuth.Operation.LOGOUT,
74
+ });
75
+
76
+ console.log('appleAuthRequestResponse logout', appleAuthRequestResponse);
77
+
78
+ return { authorizationCode: appleAuthRequestResponse.authorizationCode };
79
+ } catch (error: any) {
80
+ if (error.code === appleAuth.Error.CANCELED) {
81
+ throw { error: 'User Cancel Logout', code: error.code };
82
+ } else {
83
+ throw { error: 'Logout Request Fail', code: error.code };
84
+ }
85
+ }
86
+ },
87
+
88
+ requestDeleteAccount: async () => {
89
+ if (appleAuth.isSupported) {
90
+ const { authorizationCode } =
91
+ await AppleLoginUtil.requestAppleUserForLogout();
92
+ console.log('get authorizationCode success', authorizationCode);
93
+ const { token } = await AV.Cloud.run('getToken', {
94
+ authorizationCode,
95
+ bundleId: getBundleId(),
96
+ });
97
+ console.log('get token success', token);
98
+ await AV.Cloud.run('revokeAppleAccount', {
99
+ token,
100
+ bundleId: getBundleId(),
101
+ });
102
+ console.log('revoke account success');
103
+ }
104
+ },
105
+ };
106
+
107
+ export default AppleLoginUtil;
@@ -0,0 +1,134 @@
1
+ import AsyncStorage from '@react-native-community/async-storage';
2
+
3
+ const EventEmitter = require('events').EventEmitter;
4
+ const eventEmitter = new EventEmitter();
5
+
6
+ let isDataLoaded = false;
7
+
8
+ export interface PrefType {
9
+ key: string;
10
+ type: string;
11
+ default: any;
12
+ }
13
+
14
+ export interface PrefsType {
15
+ [key: string]: PrefType;
16
+ }
17
+
18
+ const _PrefDatas: { [key: string]: any } = {};
19
+
20
+ export const BuildInPrefs: PrefsType = {
21
+ LastLoginType: {
22
+ key: 'LastLoginType_Key',
23
+ type: 'int',
24
+ default: -1,
25
+ },
26
+ isFirstLaunch: {
27
+ key: 'isFirstLaunch_Key2',
28
+ type: 'bool',
29
+ default: true,
30
+ },
31
+ };
32
+
33
+ const getPrefByKey = (Prefs: PrefsType, key: string) => {
34
+ for (const keyOfPref in Prefs) {
35
+ if (Prefs[keyOfPref].key === key) {
36
+ return Prefs[keyOfPref];
37
+ }
38
+ }
39
+ return null;
40
+ };
41
+
42
+ export const PrefData = {
43
+ load: async (initPrefs: PrefsType) => {
44
+ console.log('读取配置');
45
+ let keys = [];
46
+ const Prefs = { ...BuildInPrefs, ...initPrefs };
47
+ for (const pref in Prefs) {
48
+ keys.push(Prefs[pref].key);
49
+ }
50
+ const values = await getMultiDatas(keys);
51
+
52
+ for (let i = 0; i < values.length; i++) {
53
+ const key = values[i][0];
54
+ const value = values[i][1];
55
+ const pref = getPrefByKey(Prefs, key);
56
+ if (!pref) {
57
+ continue;
58
+ }
59
+ // console.log(key, value, pref);
60
+ if (!value) {
61
+ _PrefDatas[key] = pref.default;
62
+ } else if (pref.type === 'object' || pref.type === 'array') {
63
+ _PrefDatas[key] = JSON.parse(value);
64
+ } else if (pref.type === 'int') {
65
+ _PrefDatas[key] = parseInt(value, 10);
66
+ } else if (pref.type === 'bool') {
67
+ _PrefDatas[key] = JSON.parse(value);
68
+ } else {
69
+ _PrefDatas[key] = value;
70
+ }
71
+ // console.log(
72
+ // '配置读取结果:',
73
+ // key,
74
+ // _PrefDatas[key],
75
+ // typeof _PrefDatas[key],
76
+ // );
77
+ }
78
+
79
+ eventEmitter.emit('load');
80
+ isDataLoaded = true;
81
+ },
82
+
83
+ getValue: (pref: PrefType) => {
84
+ return _PrefDatas[pref.key];
85
+ },
86
+
87
+ setValue: async (pref: PrefType, value: any) => {
88
+ const key = pref.key;
89
+ let finalValue: string;
90
+ _PrefDatas[key] = value;
91
+ if (pref.type === 'object' || pref.type === 'array') {
92
+ finalValue = JSON.stringify(value);
93
+ } else if (pref.type === 'int') {
94
+ finalValue = value.toString();
95
+ } else if (pref.type === 'bool') {
96
+ finalValue = value.toString();
97
+ } else {
98
+ finalValue = value;
99
+ }
100
+
101
+ await storeData(key, finalValue);
102
+ },
103
+
104
+ addListener: (callback: Function) => {
105
+ if (isDataLoaded) {
106
+ callback && callback();
107
+ return;
108
+ }
109
+ eventEmitter.on('load', callback);
110
+ },
111
+ };
112
+
113
+ const storeData = async (key: string, value: string) => {
114
+ try {
115
+ if (typeof value !== 'string') {
116
+ console.error('只接受 String');
117
+ }
118
+ // console.log('save to storage ' + value);
119
+ await AsyncStorage.setItem(key, value);
120
+ } catch (e) {
121
+ console.error(e);
122
+ }
123
+ };
124
+
125
+ const getMultiDatas = async (keys: string[]) => {
126
+ try {
127
+ const values = await AsyncStorage.multiGet(keys);
128
+ // console.log('read from storage ' + values);
129
+ return values;
130
+ } catch (e) {
131
+ console.error(e);
132
+ return [];
133
+ }
134
+ };
@@ -0,0 +1,138 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+ import {
3
+ getBrand,
4
+ getDeviceId,
5
+ getModel,
6
+ getReadableVersion,
7
+ } from 'react-native-device-info';
8
+ import { Notification } from './Notification';
9
+ import { UserType } from './constant';
10
+
11
+ export interface ReportItemType {
12
+ [key: string]: number | string;
13
+ }
14
+
15
+ const CommonInfo: ReportItemType = {
16
+ appVer: getReadableVersion(),
17
+ platform: Platform.OS,
18
+ sysVer: Platform.Version,
19
+ model: getModel(),
20
+ brand: getBrand(),
21
+ device: getDeviceId(),
22
+ };
23
+
24
+ const enable = () => {
25
+ if (__DEV__) {
26
+ return false;
27
+ }
28
+ if (!NativeModules.NCYReport) {
29
+ return false;
30
+ }
31
+ return true;
32
+ };
33
+
34
+ const isValidReport = (eventId: string, params?: ReportItemType) => {
35
+ if (typeof eventId !== 'string' || eventId?.length === 0) {
36
+ console.error('Report 数据非法 1');
37
+ return false;
38
+ }
39
+
40
+ if (params == null) {
41
+ return true;
42
+ }
43
+
44
+ if (typeof params !== 'object' || Array.isArray(params)) {
45
+ console.error('Report 数据非法 2');
46
+ return false;
47
+ }
48
+
49
+ for (const key in params) {
50
+ if (typeof key !== 'string') {
51
+ console.error('Report 数据非法 3');
52
+ return false;
53
+ }
54
+ }
55
+
56
+ return true;
57
+ };
58
+
59
+ const convertToValidParams = (params?: ReportItemType) => {
60
+ const ret: ReportItemType = {};
61
+ for (const key in params) {
62
+ const value = JSON.stringify(params[key]);
63
+ ret[key] = value;
64
+ }
65
+ return ret;
66
+ };
67
+
68
+ const ReportUtil = {
69
+ init: () => {
70
+ if (!enable()) {
71
+ return;
72
+ }
73
+
74
+ Notification.addListener(
75
+ 'onLogin',
76
+ ({ error, user }: { error: any; user: UserType }) => {
77
+ if (!error && user) {
78
+ NativeModules.NCYReport.signIn(user.AVUser.get('objectId'));
79
+ ReportUtil.setCommonInfo('user', user.AVUser.get('objectId'));
80
+ }
81
+ }
82
+ );
83
+
84
+ Notification.addListener('onLogout', () => {
85
+ NativeModules.NCYReport.signOut();
86
+ ReportUtil.setCommonInfo('user', '');
87
+ });
88
+ },
89
+
90
+ report: (eventId: string, params?: ReportItemType) => {
91
+ if (!enable()) {
92
+ return;
93
+ }
94
+
95
+ if (!isValidReport(eventId, params)) {
96
+ return;
97
+ }
98
+
99
+ const validParams = convertToValidParams(params);
100
+ const realParams = { ...validParams, ...ReportUtil.getCommonInfo() };
101
+ console.log(realParams);
102
+ NativeModules.NCYReport.report(eventId, realParams);
103
+ },
104
+
105
+ setCommonInfo: (key: string, value: string) => {
106
+ CommonInfo[key] = value;
107
+ },
108
+
109
+ getCommonInfo: () => {
110
+ return CommonInfo;
111
+ },
112
+
113
+ viewAppear: (page: string) => {
114
+ if (!__DEV__) {
115
+ console.log(page, 'viewWillAppear');
116
+ }
117
+
118
+ if (!enable()) {
119
+ return;
120
+ }
121
+
122
+ NativeModules.NCYReport.enterPage(page);
123
+ },
124
+
125
+ viewDisappear: (page: string) => {
126
+ if (!__DEV__) {
127
+ console.log(page, 'viewWillDisappear');
128
+ }
129
+
130
+ if (!enable()) {
131
+ return;
132
+ }
133
+
134
+ NativeModules.NCYReport.leavePage(page);
135
+ },
136
+ };
137
+
138
+ export default ReportUtil;
@@ -0,0 +1,49 @@
1
+ import { Notification, UserType } from '@norcy/react-native-toolkit';
2
+ import * as Sentry from '@sentry/react-native';
3
+
4
+ const SentryManager = {
5
+ init: () => {
6
+ if (__DEV__) {
7
+ console.log('__DEV__ 下不使用 Sentry');
8
+ } else {
9
+ // DEV 下不打开 Sentry
10
+ console.log('__RELEASE__ 下使用 Sentry');
11
+ Sentry.init({
12
+ dsn: 'https://a67f2741a16c45c4a66527b8f8b046a2@o473216.ingest.sentry.io/6509175',
13
+ tracesSampleRate: 1.0,
14
+ });
15
+
16
+ Notification.addListener(
17
+ 'onLogin',
18
+ ({ error, user }: { error: any; user: UserType }) => {
19
+ if (!error && user) {
20
+ const sentryUser: Sentry.User = {
21
+ id: user.AVUser.get('objectId'),
22
+ email: user.email,
23
+ username: user.nickname,
24
+ };
25
+ Sentry.setUser(sentryUser);
26
+ }
27
+ }
28
+ );
29
+
30
+ Notification.addListener('onLogout', () => {
31
+ Sentry.setUser(null);
32
+ });
33
+
34
+ // Sentry.nativeCrash();
35
+ // Sentry.captureException(new Error('测试77!'));
36
+ // throw new Error('My first Sentry error!');
37
+ }
38
+ },
39
+
40
+ setTag: (key: string, value: any) => {
41
+ if (!__DEV__) {
42
+ if (key.length) {
43
+ Sentry.setTag(key, value);
44
+ }
45
+ }
46
+ },
47
+ };
48
+
49
+ export default SentryManager;
@@ -0,0 +1,20 @@
1
+ import { User } from 'leancloud-storage';
2
+
3
+ export interface UserType {
4
+ nickname: string;
5
+ email: string;
6
+ headimgurl: string;
7
+ type: number;
8
+ AVUser: User;
9
+ }
10
+
11
+ export enum LoginState {
12
+ NOTLOGIN,
13
+ AUTHORIZED,
14
+ }
15
+
16
+ export enum LoginType {
17
+ LoginTypeApple,
18
+ LoginTypeWeChat,
19
+ LoginTypeVisitor,
20
+ }
package/src/index.tsx CHANGED
@@ -9,3 +9,8 @@ const { ReactNativeToolkit } = NativeModules;
9
9
  export default ReactNativeToolkit as ReactNativeToolkitType;
10
10
  export * from './SyncPrefData';
11
11
  export * from './Notification';
12
+ export * from './ReportUtil';
13
+ export * from './SentryManager';
14
+ export * from './AppleLoginUtil';
15
+ export * from './constant';
16
+ export * from './PrefData';