diff --git a/.changeset/v4-api-migration.md b/.changeset/v4-api-migration.md new file mode 100644 index 00000000..5844fab7 --- /dev/null +++ b/.changeset/v4-api-migration.md @@ -0,0 +1,133 @@ +--- +'@fingerprintjs/fingerprintjs-pro-react-native': major +--- + +Migrated the SDK to Fingerprint API v4 and realigned the public API with `@fingerprint/react`. This is a breaking change on every platform (web, iOS, Android). + +**Renamed API** + +- `FingerprintJsProProvider` → `FingerprintProvider`. +- `FingerprintJsProAgent` (constructed with `new`) → `start(options)`, returning a client with a single `get(options)` method (`getVisitorId`/`getVisitorData` are removed). +- Added `useFingerprint()` to read the client from context. + +**Single options object** + +- `getData(tags, linkedId, options)` → `getData({ tags, linkedId, timeout })`. +- `useVisitorData` now returns a discriminated union (`data`/`isLoading`/`isFetched`/`error`), and `getData` always throws on error. The `throwOnError` option is removed. `immediate` defaults to `false`. + +**Grouped provider/start options** + +- Platform-only options are nested: `android` (`allowUseOfLocationData`, `locationTimeoutMillis`), `ios` (`allowUseOfLocationData`), `web` (`storageKeyPrefix`, `urlHashing`, `cache`). `locationTimeoutMillisAndroid` moves to `android.locationTimeoutMillis`. +- `endpointUrl` + `fallbackEndpointUrls` are replaced by a single `endpoints` (string or string[]). + +**snake_case response** + +- The response is now the flat, snake_case `FingerprintResponse` (`visitor_id`, `event_id`, `suspect_score?`, `sealed_result`), matching the Server API v4 and JS agent. `requestId` is replaced by `event_id`, `confidence` is removed, and `suspect_score` is a new optional Smart Signals value; `sealedResult` is renamed to `sealed_result`. The nested extended fields (`ipLocation`, `firstSeenAt`, etc.) and the `extendedResponseFormat` option are removed (v4 always returns the flat format). + +**Single error type** + +- The ~28 error classes are replaced by a single `FingerprintError` (`{ name, code, event_id }`) plus an `isFingerprintError` type guard. Discriminate on `error.code` (e.g. `too_many_requests`). +- Every network failure reports `code: 'network_error'` on all platforms. The platform-specific `network_unavailable` (Android), `network_connection` and `network_abort` (web) codes are not emitted. + +**Web** + +- The web implementation now uses `@fingerprint/agent` (v4) instead of `@fingerprintjs/fingerprintjs-pro-spa`. Install `@fingerprint/agent` as the web peer dependency. +- ️Caching is available only on **web** and is disabled by default. To enable caching on web, pass the JavaScript agent [cache](https://docs.fingerprint.com/reference/js-agent-start-function#cache) option: + ```jsx + + + + ``` + +**iOS**: +- The new version floor for iOS is **15.1**. + +**Android**: +- The new version floor for Android is **Android 7.0 (API level 24+)**. + +## Migration + +**Provider** + +```diff +- import { FingerprintJsProProvider } from '@fingerprintjs/fingerprintjs-pro-react-native' ++ import { FingerprintProvider } from '@fingerprintjs/fingerprintjs-pro-react-native' + +- ++ + +- ++ +``` + +**Hook (`useVisitorData`)** + +```diff +- const { isLoading, error, data, getData } = useVisitorData() ++ const { isLoading, isFetched, error, data, getData } = useVisitorData() + + // positional args + opt-in throwing → single options object, always throws +- await getData({ userAction: 'login' }, 'user_1234', { timeout: 5000, throwOnError: true }) ++ await getData({ tags: { userAction: 'login' }, linkedId: 'user_1234', timeout: 5000 }) + +- data?.visitorId +- data?.confidence.score ++ data?.visitor_id ++ data?.suspect_score +``` + +**Imperative client** + +```diff +- import { FingerprintJsProAgent } from '@fingerprintjs/fingerprintjs-pro-react-native' ++ import { start } from '@fingerprintjs/fingerprintjs-pro-react-native' + +- const client = new FingerprintJsProAgent({ apiKey: 'PUBLIC_API_KEY', region: 'eu' }) +- const visitorId = await client.getVisitorId() +- const data = await client.getVisitorData() ++ const fp = start({ apiKey: 'PUBLIC_API_KEY', region: 'eu' }) ++ const result = await fp.get() ++ result.visitor_id +``` + +**Provider / start options** + +```diff + { + apiKey: 'PUBLIC_API_KEY', + region: 'eu', +- endpointUrl: 'https://metrics.example.com', +- fallbackEndpointUrls: ['https://metrics2.example.com'], ++ endpoints: ['https://metrics.example.com', 'https://metrics2.example.com'], +- extendedResponseFormat: true, +- allowUseOfLocationData: true, +- locationTimeoutMillisAndroid: 5000, ++ android: { allowUseOfLocationData: true, locationTimeoutMillis: 5000 }, ++ ios: { allowUseOfLocationData: true }, + } +``` + +**Errors** + +```diff +- import { TooManyRequestError } from '@fingerprintjs/fingerprintjs-pro-react-native' ++ import { isFingerprintError } from '@fingerprintjs/fingerprintjs-pro-react-native' + + try { + await fp.get() + } catch (error) { +- if (error instanceof TooManyRequestError) { ++ if (isFingerprintError(error) && error.code === 'too_many_requests') { + // handle rate limiting + } + } +``` + +**Web peer dependency** + +```diff +- npm install @fingerprintjs/fingerprintjs-pro-spa ++ npm install @fingerprint/agent +``` + +--- \ No newline at end of file diff --git a/README.md b/README.md index 8f0f4f38..192a1c28 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ application to call the native Fingerprint Pro libraries (Android and iOS) and i - [Dependencies](#dependencies) - [How to install](#how-to-install) - [Expo setup](#expo-setup) - - [1. Add config plugin](#1-add-config-plugin) - - [2. Rebuild the native code](#2-rebuild-the-native-code) - - [3. Rebuild the app](#3-rebuild-the-app) + - [1. Add config plugin](#1-add-config-plugin) + - [2. Rebuild the native code](#2-rebuild-the-native-code) + - [3. Rebuild the app](#3-rebuild-the-app) - [Bare react-native](#bare-react-native-setup) - [1. Configure iOS dependencies (if developing on iOS)](#1-configure-ios-dependencies-if-developing-on-ios) - [2. Configure Android dependencies (if developing on Android)](#2-configure-android-dependencies-if-developing-on-android) @@ -53,7 +53,8 @@ application to call the native Fingerprint Pro libraries (Android and iOS) and i - [Usage](#usage) - [Hooks approach](#hooks-approach) - [API Client approach](#api-client-approach) - - [`extendedResponseFormat`](#extendedresponseformat) + - [Response format](#response-format) + - [Error handling](#error-handling) - [Linking and tagging information](#linking-and-tagging-information) - [API Reference](#api-reference) - [Additional Resources](#additional-resources) @@ -64,8 +65,8 @@ application to call the native Fingerprint Pro libraries (Android and iOS) and i - React Native 0.79 or higher is supported (New Architecture only) - Expo 53.0.0 or higher is supported -- Android 6.0 (API level 23+) or higher -- iOS 13+/tvOS 15+, Swift 5.9 or higher (stable releases) +- Android 7.0 (API level 24+) or higher +- iOS 15.1+/tvOS 15.1+, Swift 5.9 or higher (stable releases) - Fingerprint Pro [request filtering](https://dev.fingerprint.com/docs/request-filtering) is not supported right now. Allowed and forbidden origins cannot be used. @@ -94,7 +95,7 @@ Install the package using your favorite package manager: ```shell pnpm add @fingerprintjs/fingerprintjs-pro-react-native ``` - + ## Expo setup > ℹ️ Our SDK cannot be used in [Expo Go](https://expo.dev/go) because it requires custom native code. @@ -106,20 +107,20 @@ To use the SDK on the web, install the peer dependency with your preferred packa - [NPM](https://npmjs.org): ```shell - npm install @fingerprintjs/fingerprintjs-pro-spa --save + npm install @fingerprint/agent --save ``` - [Yarn](https://yarnpkg.com): ```shell - yarn add @fingerprintjs/fingerprintjs-pro-spa + yarn add @fingerprint/agent ``` - [PNPM](https://pnpm.js.org): ```shell - pnpm add @fingerprintjs/fingerprintjs-pro-spa + pnpm add @fingerprint/agent ``` - + Then, use the SDK as you would with the native version. @@ -149,7 +150,7 @@ For iOS: ```bash npx expo run:ios ``` - + ## Bare react-native setup ### 1. Configure iOS dependencies (if developing on iOS) @@ -185,22 +186,22 @@ For Gradle versions before 7.0, you likely have an `allprojects` block in `{root ```groovy allprojects { - repositories { - mavenCentral() - mavenLocal() - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url("$rootDir/../node_modules/react-native/android") - } - maven { - // Android JSC is installed from npm - url("$rootDir/../node_modules/jsc-android/dist") - } - maven { - url("https://maven.fpregistry.io/releases") // Add this - } - google() + repositories { + mavenCentral() + mavenLocal() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url("$rootDir/../node_modules/react-native/android") + } + maven { + // Android JSC is installed from npm + url("$rootDir/../node_modules/jsc-android/dist") } + maven { + url("https://maven.fpregistry.io/releases") // Add this + } + google() + } } ``` @@ -213,20 +214,20 @@ To identify visitors, you need a Fingerprint Pro account (you can [sign up for f ### Hooks approach -Configure the SDK by wrapping your application in FingerprintJsProProvider. +Configure the SDK by wrapping your application in `FingerprintProvider`. ```javascript // src/index.js import React from 'react'; import { AppRegistry } from 'react-native'; -import { FingerprintJsProProvider } from '@fingerprintjs/fingerprintjs-pro-react-native'; +import { FingerprintProvider } from '@fingerprintjs/fingerprintjs-pro-react-native'; import App from './App'; import { name as appName } from './app.json'; const WrappedApp = () => ( - - - + + + ) AppRegistry.registerComponent(appName, () => WrappedApp); @@ -241,42 +242,54 @@ import {Button, SafeAreaView, Text, View} from 'react-native' import {useVisitorData} from '@fingerprintjs/fingerprintjs-pro-react-native' export default function App() { - const {isLoading, error, data, getData} = useVisitorData() + const {isLoading, isFetched, error, data, getData} = useVisitorData() return ( - - -