Skip to content

Commit f34dec6

Browse files
committed
docs: create documentation about integration with sdl
1 parent 35b29ae commit f34dec6

File tree

6 files changed

+121
-20
lines changed

6 files changed

+121
-20
lines changed

README.md

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,114 @@
11
# react-native-contentpass
22

3-
Contentpass React Native SDK
3+
Contentpass React Native SDK enables easy integration of Contentpass functionality into your React Native applications.
44

55
## Installation
6+
Install the package using npm or Yarn:
67

78
```sh
89
npm install react-native-contentpass
910
```
1011

12+
or
13+
14+
```sh
15+
yarn add react-native-contentpass
16+
```
17+
18+
### Peer Dependencies
19+
The following peer dependencies must also be installed:
20+
- [react](https://github.com/facebook/react) (Required for React Native projects.)
21+
- [react-native](https://github.com/facebook/react-native) (Core React Native framework)
22+
- [react-native-app-auth](https://github.com/FormidableLabs/react-native-app-auth) (Used for OAuth 2.0 authentication)
23+
- [react-native-encrypted-storage](https://github.com/emeraldsanto/react-native-encrypted-storage) (Ensures secure storage of authentication tokens)
24+
25+
Some dependencies require additional setup in the native code. Refer to their official guides:
26+
- [react-native-app-auth setup](https://commerce.nearform.com/open-source/react-native-app-auth/docs#setup)
27+
- [react-native-encrypted-storage setup](https://github.com/emeraldsanto/react-native-encrypted-storage?tab=readme-ov-file#installation)
28+
29+
### Expo support
30+
If you are using Expo, you need to run the following command to enable modifications to the `ios` and `android` directories:
31+
32+
```sh
33+
npx expo prebuild
34+
```
35+
1136
## Usage
1237

38+
### Initialization
39+
Wrap your app's root component with ContentpassSdkProvider. The provider requires a configuration object (contentpassConfig) with the following properties:
40+
- `propertyId` - Your unique property ID
41+
- `issuer` - The OAuth 2.0 server URL (e.g. `https://my.contentpass.net`)
42+
- `redirectUrl` - the redirect URL of your app to which the OAuth2 server will redirect after the authentication
43+
44+
45+
```jsx
46+
import React from 'react';
47+
import { ContentpassSdkProvider } from 'react-native-contentpass';
48+
49+
const contentpassConfig = {
50+
propertyId: 'your-property-id',
51+
issuer: 'https://my.contentpass.net',
52+
redirectUrl: 'com.yourapp://oauthredirect',
53+
};
54+
55+
const App = () => {
56+
return (
57+
<ContentpassSdkProvider contentpassConfig={contentpassConfig}>
58+
<YourApp />
59+
</ContentpassSdkProvider>
60+
);
61+
};
62+
63+
export default App;
64+
```
65+
66+
### SDK Methods
67+
The SDK exposes the following methods through the `useContentpassSdk` hook:
68+
69+
### authenticate
70+
Initiates the OAuth 2.0 authentication process via a modal interface. It validates the user’s active Contentpass subscriptions
71+
upon successful authentication.
72+
73+
### registerObserver
74+
Registers a callback function to listen for changes in the user’s authentication and subscription status. The observer function
75+
receives a state object describing the current status (see the exported [ContentpassState](./src/types/ContentpassState.ts) type).
76+
77+
### unregisterObserver
78+
Unregisters a previously registered observer. The observer will no longer receive updates.
79+
80+
### logout
81+
Logs the user out by clearing all stored authentication tokens.
82+
83+
### recoverFromError
84+
During background token refresh, an error state may occur due to poor or no internet connection. This is indicated by the
85+
`state` switching to `ERROR`. The state object includes a reference to the original exception that was thrown. As the SDK
86+
does not monitor the device's connection state, you must notify the SDK when the network connection has been reestablished
87+
or improved. The SDK will then refresh and revalidate the user's authentication tokens.
88+
89+
```jsx
90+
import React, { useEffect } from 'react';
91+
import { useContentpassSdk } from 'react-native-contentpass';
92+
93+
const YourApp = () => {
94+
const { authenticate, registerObserver, unregisterObserver, logout, recoverFromError } = useContentpassSdk();
95+
96+
useEffect(() => {
97+
const observer = (state) => {
98+
console.log('Contentpass state changed:', state);
99+
};
13100

14-
```js
15-
import { multiply } from 'react-native-contentpass';
101+
registerObserver(observer);
16102

17-
// ...
103+
return () => {
104+
unregisterObserver(observer);
105+
};
106+
}, []);
18107

19-
const result = await multiply(3, 7);
108+
return (
109+
<button onClick={authenticate}>Authenticate</button>
110+
);
111+
};
20112
```
21113

22114

sharedExample/src/ContentpassUsage.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ import {
1111
import setupSourcepoint from './setupSourcepoint';
1212

1313
const styles = StyleSheet.create({
14-
sourcepointDataContainer: {
14+
scrollViewLogsContainer: {
1515
padding: 10,
16-
height: 400,
16+
height: 200,
1717
flexGrow: 0,
1818
},
19+
resultsText: {
20+
marginTop: 20,
21+
fontWeight: 'bold',
22+
},
1923
buttonsContainer: {
2024
display: 'flex',
2125
gap: 4,
@@ -84,10 +88,12 @@ export default function ContentpassUsage() {
8488
<Button title={'Logout'} onPress={contentpassSdk.logout} />
8589
</View>
8690
<View style={styles.logsView}>
87-
<Text>Authenticate result:</Text>
88-
<Text>{JSON.stringify(authResult, null, 2)}</Text>
89-
<Text>Sourcepoint user data:</Text>
90-
<ScrollView style={styles.sourcepointDataContainer}>
91+
<Text style={styles.resultsText}>Authenticate result:</Text>
92+
<ScrollView style={styles.scrollViewLogsContainer}>
93+
<Text>{JSON.stringify(authResult, null, 2)}</Text>
94+
</ScrollView>
95+
<Text style={styles.resultsText}>Sourcepoint user data:</Text>
96+
<ScrollView style={styles.scrollViewLogsContainer}>
9197
<Text>{JSON.stringify(sourcepointUserData, null, 2)}</Text>
9298
</ScrollView>
9399
</View>

src/Contentpass.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ describe('Contentpass', () => {
186186
expect(contentpassStates).toHaveLength(2);
187187
expect(contentpassStates[1]).toEqual({
188188
state: 'ERROR',
189-
error: 'Authorize error',
189+
error,
190190
});
191191
});
192192

@@ -213,7 +213,8 @@ describe('Contentpass', () => {
213213
contentpass.registerObserver((state) => {
214214
contentpassStates.push(state);
215215
});
216-
fetchContentpassTokenSpy.mockRejectedValue(new Error('Fetch error'));
216+
const error = new Error('Fetch error');
217+
fetchContentpassTokenSpy.mockRejectedValue(error);
217218

218219
await contentpass.authenticate();
219220

@@ -223,7 +224,7 @@ describe('Contentpass', () => {
223224
expect(contentpassStates).toHaveLength(2);
224225
expect(contentpassStates[1]).toEqual({
225226
state: 'ERROR',
226-
error: 'Fetch error',
227+
error,
227228
});
228229
});
229230

@@ -410,13 +411,14 @@ describe('Contentpass', () => {
410411
contentpassStates.push(state);
411412
});
412413

413-
authorizeSpy.mockRejectedValue(new Error('Authorize error'));
414+
const error = new Error('Authorize error');
415+
authorizeSpy.mockRejectedValue(error);
414416

415417
await contentpass.authenticate();
416418

417419
expect(contentpassStates[1]).toEqual({
418420
state: 'ERROR',
419-
error: 'Authorize error',
421+
error,
420422
});
421423

422424
await contentpass.recoverFromError();

src/Contentpass.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default class Contentpass {
5757

5858
this.changeContentpassState({
5959
state: ContentpassStateType.ERROR,
60-
error: 'message' in err ? err.message : 'Unknown error',
60+
error: err,
6161
});
6262
return;
6363
}
@@ -133,7 +133,7 @@ export default class Contentpass {
133133
} catch (err: any) {
134134
this.changeContentpassState({
135135
state: ContentpassStateType.ERROR,
136-
error: err.message || 'Unknown error',
136+
error: err,
137137
});
138138
}
139139
};

src/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export type {
22
ContentpassState,
3+
ContentpassStateType,
34
ErrorState,
45
AuthenticatedState,
56
InitialisingState,
@@ -9,7 +10,7 @@ export type {
910
export type { ContentpassConfig } from './types/ContentpassConfig';
1011

1112
export {
12-
default as Contentpass,
13+
type default as Contentpass,
1314
type ContentpassObserver,
1415
} from './Contentpass';
1516

src/types/ContentpassState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export type AuthenticatedState = {
2828
export type ErrorState = {
2929
state: ContentpassStateType.ERROR;
3030
hasValidSubscription?: never;
31-
error: string;
31+
error: unknown;
3232
};
3333

3434
export type ContentpassState =

0 commit comments

Comments
 (0)