@soyio/soyio-rn-sdk 0.1.0

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 ADDED
@@ -0,0 +1,156 @@
1
+ <h1 align="center">Soyio React Native</h1>
2
+
3
+ <p align="center">
4
+ <em>
5
+ Use the Soyio widget within your React Native application as a View.
6
+ </em>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/@soyio/soyio-rn-sdk" target="_blank">
11
+ <img src="https://img.shields.io/npm/v/@soyio/soyio-rn-sdk?label=version&logo=nodedotjs&logoColor=%23fff&color=306998" alt="NPM - Version">
12
+ </a>
13
+ </p>
14
+
15
+ ## Installation
16
+
17
+ Install using npm! (or your favorite package manager)
18
+
19
+ ```sh
20
+ # Using npm
21
+ npm install @soyio/soyio-rn-sdk
22
+
23
+ # Using yarn
24
+ yarn add @soyio/soyio-rn-sdk
25
+ ```
26
+
27
+ **IMPORTANT:**
28
+ For developers working with a bare React Native application, it is essential to include Expo modules to ensure full compatibility and functionality of the Soyio SDK. To install Expo modules, run the following command in your project directory:
29
+
30
+ ```bash
31
+ npx install-expo-modules
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ `Soyio React Native` exports a single hook called `useSoyioAuth`. This is a hook that opens a `WebBrowser` using the `openAuthSessionAsync` method by [expo](https://docs.expo.dev/versions/latest/sdk/webbrowser/#webbrowseropenauthsessionasyncurl-redirecturl-options).
37
+
38
+ To use the Soyio hook, use the following _snippet_:
39
+
40
+ ```js
41
+ import { useSoyioAuth } from "@soyio/soyio-rn-sdk";
42
+ ```
43
+
44
+ After retrieving the `useSoyioAuth` hook, you are ready to instantiate the widget:
45
+
46
+ ```jsx
47
+ export default function App() {
48
+ const options = {
49
+ userReference: "<company identifier of user>", // OPTIONAL
50
+ companyId: "<company id>", // Starts with 'com_'
51
+ isSandbox: true, // Optional. Default is false
52
+ };
53
+
54
+ // For registering a new identity
55
+ const registerParams = {
56
+ flowTemplateId: "<flow template id>", // Starts with 'vft_'
57
+ userEmail: "<user email>", // OPTIONAL
58
+ };
59
+
60
+ // For authenticate existing identity
61
+ const authenticateParams = {
62
+ identityId: "<identity id>", // Starts with 'id_'
63
+ };
64
+
65
+ const onEventChange = (event) => {
66
+ console.log("Event:", event);
67
+ };
68
+
69
+ const { register, authenticate } = useSoyioAuth({ options, onEventChange });
70
+
71
+ const registerNewIdentity = () => {
72
+ register(registerParams);
73
+ };
74
+
75
+ const authenticateIdentity = () => {
76
+ authenticate(authenticateParams);
77
+ };
78
+
79
+ return (
80
+ <View>
81
+ <Button title="Register new user" onPress={registerNewIdentity} />
82
+ <Button title="Authenticate identity" onPress={authenticateIdentity} />
83
+ </View>
84
+ );
85
+ }
86
+ ```
87
+
88
+ In this implementation, the `WebBrowser` will not open until either `register()` or `authenticate()` is invoked.
89
+
90
+ The `onEventChange` function returns an object with the following properties:
91
+
92
+ - `type`: Indicates the type of event being triggered. Possible values are:
93
+
94
+ - `"open register"`: Triggered when the user initiates the `register` method.
95
+ - `"open authenticate"`: Triggered when the user initiates the `authenticate` method.
96
+ - `"close"`: Triggered when the user closes the `WebBrowser`.
97
+ - `"success"`: Triggered when the authentication flow is successfully completed.
98
+
99
+ - `url` (optional): URL associated only with the `success` event.
100
+
101
+ - For registration: `"demo://registered?userReference=<company user reference>&id=<identity_id>"`
102
+ - For authentication: `"demo://authenticated?userReference=<company user reference>&id=<identity_id>"`
103
+
104
+ where `<identity_id>` is the unique identifier of the newly registered or authenticated user, respectively.
105
+
106
+ The `onEventChange` function should be defined as follows:
107
+
108
+ ```typescript
109
+ onEventChange?: (event: { type: string; url?: string }) => void;
110
+ ```
111
+
112
+ ## TypeScript support
113
+
114
+ This package includes TypeScript declarations for the Soyio View.
115
+
116
+ ## Developing
117
+
118
+ To develop the package, you need to use `npm`. Install the dependencies:
119
+
120
+ ```sh
121
+ npm install
122
+ ```
123
+
124
+ To test locally, I recommend packaging the app. Remember to build the library first:
125
+
126
+ ```sh
127
+ npm run build
128
+ npm pack
129
+ ```
130
+
131
+ This will create a `soyio-soyio-rn-sdk-x.x.x.tgz` file (with the corresponding package version). Now, go to another directory and create a React Native app (using Expo, perhaps). After creating the new application, add the following dependency to its `package.json` file:
132
+
133
+ ```json
134
+ {
135
+ "dependencies": {
136
+ ...,
137
+ "@soyio/soyio-rn-sdk": "file:./path/to/soyio-soyio-rn-sdk-x.x.x.tgz",
138
+ ...
139
+ }
140
+ }
141
+ ```
142
+
143
+ Where `./path/to/soyio-soyio-rn-sdk-x.x.x.tgz` corresponds to the path to the `.tgz` file created on the `npm pack` step. After running `npm install` on the new React Native app, you should be able to use Soyio React Native to import the Soyio View.
144
+
145
+ If you want to create a new _release_, you can run:
146
+
147
+ ```sh
148
+ git switch main
149
+ npm run bump! <major|minor|patch>
150
+ ```
151
+
152
+ This will create a new branch with the updated version from `main`.
153
+
154
+ ## Acknowledgements
155
+
156
+ This implementation was written based on the input and experience of [**fintoc**](https://github.com/fintoc-com/fintoc-react-native) integrating the WebView using React Native, which served as a good starting point for the general idea of this library.
package/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export { useSoyioAuth } from './src/core';
2
+
3
+ export type {
4
+ SoyioWidgetParams,
5
+ RegisterParams,
6
+ AuthenticateParams,
7
+ SoyioWidgetViewPropsType,
8
+ } from './src/types';
@@ -0,0 +1,2 @@
1
+ export { useSoyioAuth } from './src/core';
2
+ export type { SoyioWidgetParams, RegisterParams, AuthenticateParams, SoyioWidgetViewPropsType, } from './src/types';
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSoyioAuth = void 0;
4
+ var core_1 = require("./src/core");
5
+ Object.defineProperty(exports, "useSoyioAuth", { enumerable: true, get: function () { return core_1.useSoyioAuth; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ export declare const PRODUCTION_URL = "https://app.soyio.id/widget";
2
+ export declare const SANDBOX_URL = "https://sandbox.soyio.id/widget";
3
+ export declare const SOYIO_REDIRECT_URL = "demo://";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SOYIO_REDIRECT_URL = exports.SANDBOX_URL = exports.PRODUCTION_URL = void 0;
4
+ exports.PRODUCTION_URL = 'https://app.soyio.id/widget';
5
+ exports.SANDBOX_URL = 'https://sandbox.soyio.id/widget';
6
+ exports.SOYIO_REDIRECT_URL = 'demo://';
7
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,5 @@
1
+ import type { SoyioWidgetViewPropsType, RegisterParams, AuthenticateParams } from './types';
2
+ export declare const useSoyioAuth: ({ options, onEventChange }: SoyioWidgetViewPropsType) => {
3
+ register: (registerParams: RegisterParams) => Promise<void>;
4
+ authenticate: (authenticateParams: AuthenticateParams) => Promise<void>;
5
+ };
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __generator = (this && this.__generator) || function (thisArg, body) {
35
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
36
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37
+ function verb(n) { return function (v) { return step([n, v]); }; }
38
+ function step(op) {
39
+ if (f) throw new TypeError("Generator is already executing.");
40
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
41
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
42
+ if (y = 0, t) op = [op[0] & 2, t.value];
43
+ switch (op[0]) {
44
+ case 0: case 1: t = op; break;
45
+ case 4: _.label++; return { value: op[1], done: false };
46
+ case 5: _.label++; y = op[1]; op = [0]; continue;
47
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
48
+ default:
49
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
50
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
51
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
52
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
53
+ if (t[2]) _.ops.pop();
54
+ _.trys.pop(); continue;
55
+ }
56
+ op = body.call(thisArg, _);
57
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
58
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
+ }
60
+ };
61
+ Object.defineProperty(exports, "__esModule", { value: true });
62
+ exports.useSoyioAuth = void 0;
63
+ var react_1 = require("react");
64
+ var WebBrowser = __importStar(require("expo-web-browser"));
65
+ var utils_1 = require("./utils");
66
+ var constants_1 = require("./constants");
67
+ var useSoyioAuth = function (_a) {
68
+ var options = _a.options, onEventChange = _a.onEventChange;
69
+ var webBrowserOptions = {
70
+ dismissButtonStyle: 'cancel',
71
+ createTask: false,
72
+ enableBarCollapsing: true,
73
+ showTitle: true,
74
+ };
75
+ var register = (0, react_1.useCallback)(function (registerParams) { return __awaiter(void 0, void 0, void 0, function () {
76
+ var registerBaseUri, registerUri, registerResult;
77
+ return __generator(this, function (_a) {
78
+ switch (_a.label) {
79
+ case 0:
80
+ registerBaseUri = (0, utils_1.getFlowUrl)(options, 'register');
81
+ registerUri = "".concat(registerBaseUri, "?").concat((0, utils_1.buildUrlParams)(options, registerParams));
82
+ if (onEventChange)
83
+ onEventChange({ type: 'open register' });
84
+ return [4 /*yield*/, WebBrowser.openAuthSessionAsync(registerUri, constants_1.SOYIO_REDIRECT_URL, webBrowserOptions)];
85
+ case 1:
86
+ registerResult = _a.sent();
87
+ if (onEventChange)
88
+ onEventChange(registerResult);
89
+ return [2 /*return*/];
90
+ }
91
+ });
92
+ }); }, [options, onEventChange]);
93
+ var authenticate = (0, react_1.useCallback)(function (authenticateParams) { return __awaiter(void 0, void 0, void 0, function () {
94
+ var authenticateBaseUri, authenticateUri, authenticateResult;
95
+ return __generator(this, function (_a) {
96
+ switch (_a.label) {
97
+ case 0:
98
+ authenticateBaseUri = (0, utils_1.getFlowUrl)(options, 'authenticate');
99
+ authenticateUri = "".concat(authenticateBaseUri, "?").concat((0, utils_1.buildUrlParams)(options, authenticateParams));
100
+ if (onEventChange)
101
+ onEventChange({ type: 'open authenticate' });
102
+ return [4 /*yield*/, WebBrowser.openAuthSessionAsync(authenticateUri, constants_1.SOYIO_REDIRECT_URL, webBrowserOptions)];
103
+ case 1:
104
+ authenticateResult = _a.sent();
105
+ if (onEventChange)
106
+ onEventChange(authenticateResult);
107
+ return [2 /*return*/];
108
+ }
109
+ });
110
+ }); }, [options, onEventChange]);
111
+ return { register: register, authenticate: authenticate };
112
+ };
113
+ exports.useSoyioAuth = useSoyioAuth;
114
+ //# sourceMappingURL=core.jsx.map
@@ -0,0 +1,20 @@
1
+ export type SoyioWidgetParams = {
2
+ companyId: string;
3
+ userReference?: string;
4
+ isSandbox?: boolean;
5
+ developmentUrl?: string;
6
+ };
7
+ export type RegisterParams = {
8
+ flowTemplateId: string;
9
+ userEmail?: string;
10
+ };
11
+ export type AuthenticateParams = {
12
+ identityId: string;
13
+ };
14
+ export type SoyioWidgetViewPropsType = {
15
+ options: SoyioWidgetParams;
16
+ onEventChange?: (event: {
17
+ type: string;
18
+ url?: string;
19
+ }) => void;
20
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,3 @@
1
+ import { RegisterParams, AuthenticateParams, SoyioWidgetParams } from './types';
2
+ export declare function getFlowUrl(options: SoyioWidgetParams, flow: 'authenticate' | 'register'): string;
3
+ export declare function buildUrlParams(widgetParams: SoyioWidgetParams, flowParams: RegisterParams | AuthenticateParams): string;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildUrlParams = exports.getFlowUrl = void 0;
4
+ var constants_1 = require("./constants");
5
+ function getFlowUrl(options, flow) {
6
+ var baseUrl = options.developmentUrl || (options.isSandbox ? constants_1.SANDBOX_URL : constants_1.PRODUCTION_URL);
7
+ return "".concat(baseUrl, "/").concat(flow);
8
+ }
9
+ exports.getFlowUrl = getFlowUrl;
10
+ function buildUrlParams(widgetParams, flowParams) {
11
+ var baseParams = "platform=rn&companyId=".concat(widgetParams.companyId);
12
+ if (widgetParams.userReference) {
13
+ baseParams += "&userReference=".concat(widgetParams.userReference);
14
+ }
15
+ var dynamicParams = Object.entries(flowParams)
16
+ .map(function (_a) {
17
+ var key = _a[0], value = _a[1];
18
+ return "".concat(key, "=").concat(encodeURIComponent(value));
19
+ })
20
+ .join('&');
21
+ return "".concat(baseParams, "&").concat(dynamicParams);
22
+ }
23
+ exports.buildUrlParams = buildUrlParams;
24
+ //# sourceMappingURL=utils.js.map
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@soyio/soyio-rn-sdk",
3
+ "version": "0.1.0",
4
+ "main": "./package/index.js",
5
+ "types": "./package/index.d.ts",
6
+ "scripts": {
7
+ "bump!": "sh scripts/bump.sh",
8
+ "start": "expo start",
9
+ "android": "expo start --android",
10
+ "ios": "expo start --ios",
11
+ "web": "expo start --web",
12
+ "build": "npm run build:esm && npm run build:cjs",
13
+ "build:esm": "tsc",
14
+ "build:cjs": "tsc --module commonjs"
15
+ },
16
+ "dependencies": {
17
+ "expo": "~50.0.14",
18
+ "expo-status-bar": "~1.11.1",
19
+ "expo-web-browser": "~12.8.2",
20
+ "react": "18.2.0",
21
+ "react-native": "0.73.6"
22
+ },
23
+ "devDependencies": {
24
+ "@babel/core": "^7.20.0",
25
+ "@types/react": "~18.2.45",
26
+ "typescript": "^5.1.3"
27
+ }
28
+ }