Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 3x 3x 30x 26x 4x 4x 4x 25x 19x 6x 5x 1x 22x 30x 30x 30x 30x 30x 25x 25x 25x 25x 22x 2x 30x | import { Platform, type CodegenTypes } from 'react-native'
import RNFingerprint, { type NativeVisitorData } from './specs/NativeRNFingerprint'
import type { FingerprintClient, FingerprintResponse, GetOptions, StartOptions, TagsValue } from './types'
import { unwrapError } from './unwrapError'
import { isDefined, isTruthy } from './utils'
import { validateTags } from './tags'
const packageVersion = '__VERSION__'
const DEFAULT_LOCATION_TIMEOUT_MILLIS = 5000
/**
* Splits the {@link StartOptions.endpoints} value into a primary endpoint plus fallbacks, matching
* the positional native `configure` contract.
*/
function normalizeEndpoints(endpoints: StartOptions['endpoints']): { endpointUrl: string | null; fallbacks: string[] } {
if (!isDefined(endpoints)) {
return { endpointUrl: null, fallbacks: [] }
}
const list = Array.isArray(endpoints) ? endpoints : [endpoints]
const [primary, ...fallbacks] = list
return { endpointUrl: list.length > 0 ? primary : null, fallbacks }
}
/**
* The native SDKs model tags as a string→value map. Objects pass through unchanged; primitives and
* arrays are wrapped under a `tag` key so both iOS and Android receive a valid object.
*/
function toNativeTag(tag: TagsValue | undefined): CodegenTypes.UnsafeObject | null {
if (!isDefined(tag)) {
return null
}
if (typeof tag === 'object' && !Array.isArray(tag)) {
return tag
}
return { tag }
}
function normalizeResponse(data: NativeVisitorData): FingerprintResponse {
return {
visitor_id: isTruthy(data.visitorId) ? data.visitorId : undefined,
event_id: data.eventId,
suspect_score: data.suspectScore >= 0 ? data.suspectScore : undefined,
sealed_result: isTruthy(data.sealedResult) ? data.sealedResult : null,
}
}
class NativeFingerprintClient implements FingerprintClient {
constructor(options: StartOptions) {
const { apiKey, region, endpoints, android, ios } = options
const { endpointUrl, fallbacks } = normalizeEndpoints(endpoints)
const allowUseOfLocationData =
(Platform.OS === 'ios' ? ios?.allowUseOfLocationData : android?.allowUseOfLocationData) ?? false
const locationTimeoutMillis = android?.locationTimeoutMillis ?? DEFAULT_LOCATION_TIMEOUT_MILLIS
RNFingerprint.configure(
apiKey,
packageVersion,
fallbacks,
allowUseOfLocationData,
locationTimeoutMillis,
region ?? null,
endpointUrl
)
}
public async get(options?: GetOptions): Promise<FingerprintResponse> {
validateTags(options?.tags)
const nativeTags = toNativeTag(options?.tags)
try {
const data = await RNFingerprint.getVisitorData(nativeTags, options?.linkedId ?? null, options?.timeout ?? null)
return normalizeResponse(data)
} catch (error) {
throw unwrapError(error)
}
}
}
/**
* Creates a Fingerprint client with the given options.
*
* Applications should create only one client: either through the API client (`start()`)
* or through a single `FingerprintProvider`. Creating another client will overwrite the underlying native client of the
* previous one.
*
* @group API Client approach
*
* @example
* ```ts
* const fp = start({ apiKey: 'PUBLIC_API_KEY', region: 'eu' })
* const result = await fp.get({ linkedId: 'user_1234' })
* ```
*/
export function start(options: StartOptions): FingerprintClient {
return new NativeFingerprintClient(options)
}
|