Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@fingerprintjs/fingerprintjs-pro-server-api

Package Overview
Dependencies
Maintainers
0
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fingerprintjs/fingerprintjs-pro-server-api - npm Package Compare versions

Comparing version 4.1.2 to 5.0.0-test.1

src/errors/apiErrors.ts

4

package.json
{
"name": "@fingerprintjs/fingerprintjs-pro-server-api",
"version": "4.1.2",
"version": "5.0.0-test.1",
"description": "Node.js wrapper for FingerprintJS Sever API",

@@ -47,3 +47,3 @@ "main": "dist/index.cjs",

"@commitlint/cli": "^19.2.1",
"@fingerprintjs/commit-lint-dx-team": "^0.0.2",
"@fingerprintjs/commit-lint-dx-team": "^0.1.0",
"@fingerprintjs/conventional-changelog-dx-team": "^0.1.0",

@@ -50,0 +50,0 @@ "@fingerprintjs/eslint-config-dx-team": "^0.1.0",

@@ -12,3 +12,3 @@ <p align="center">

<a href="https://github.com/fingerprintjs/fingerprintjs-pro-server-api-node-sdk/actions/workflows/build.yml"><img src="https://github.com/fingerprintjs/fingerprintjs-pro-server-api-node-sdk/actions/workflows/build.yml/badge.svg" alt="Build status"></a>
<a href="https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/"><img src="https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/badges.svg" alt="coverage"></a>
<a href="https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/coverage"><img src="https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/coverage/badges.svg" alt="coverage"></a>
<a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs-pro-server-api"><img src="https://img.shields.io/npm/v/@fingerprintjs/fingerprintjs-pro-server-api.svg" alt="Current NPM version"></a>

@@ -73,3 +73,3 @@ <a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs-pro-server-api"><img src="https://img.shields.io/npm/dm/@fingerprintjs/fingerprintjs-pro-server-api.svg" alt="Monthly downloads from NPM"></a>

Initialize the client instance and use it to make API requests. You need to specify your Fingerprint [Secret API key](https://dev.fingerprint.com/docs/quick-start-guide#server-api) and the region of your Fingerprint application.
Initialize the client instance and use it to make API requests. You need to specify your Fingerprint [Secret API key](https://dev.fingerprint.com/docs/quick-start-guide#server-api-and-smart-signals) and the region of your Fingerprint application.

@@ -123,4 +123,5 @@ ```ts

if (isEventError(error)) {
console.log(error.responseBody) // Access parsed response body
console.log(error.response) // You can also access the raw response
console.log(`error ${error.status}: `, error.error?.message)
console.log(`error ${error.statusCode}: `, error.message)
} else {

@@ -146,5 +147,53 @@ console.log('unknown error: ', error)

}
// You can also check for specific error instance
// if(error instanceof VisitorsError403) {
// Handle 403 error...
// }
}
```
You can also check for specific error instance:
```typescript
import {
isVisitorsError,
isEventError,
FingerprintJsServerApiClient,
VisitorsError429,
} from '@fingerprintjs/fingerprintjs-pro-server-api'
const client = new FingerprintJsServerApiClient({
apiKey: '<SECRET_API_KEY>',
region: Region.Global,
})
// Handling getEvent errors
try {
const event = await client.getEvent(requestId)
console.log(JSON.stringify(event, null, 2))
} catch (error) {
if (isEventError(error)) {
console.log(error.responseBody) // Access parsed response body
console.log(error.response) // You can also access the raw response
console.log(`error ${error.statusCode}: `, error.message)
} else {
console.log('unknown error: ', error)
}
}
try {
const visitorHistory = await client.getVisitorHistory(visitorId, {
limit: 10,
})
console.log(JSON.stringify(visitorHistory, null, 2))
} catch (error) {
if (error instanceof VisitorsError429) {
retryLater(error.retryAfter) // Needs to be implemented on your side
}
throw error
}
```
### Webhooks

@@ -167,13 +216,13 @@

To learn more, see [example/validateWebhookSignature.mjs](example/validateWebhookSignature.mjs) or read the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/functions/isValidWebhookSignature.html).
To learn more, see [example/validateWebhookSignature.mjs](example/validateWebhookSignature.mjs) or read the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/functions/isValidWebhookSignature.html).
### Sealed results
Customers on the Enterprise plan can enable [Sealed results](https://dev.fingerprint.com/docs/sealed-results) to receive the full device intelligence result on the client and unseal it on the server. This SDK provides utility methods for decoding sealed results.
Customers on the Enterprise plan can enable [Sealed results](https://dev.fingerprint.com/docs/sealed-client-results) to receive the full device intelligence result on the client and unseal it on the server. This SDK provides utility methods for decoding sealed results.
To learn more, see [example/unsealResult.mjs](./example/unsealResult.mjs) or the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/functions/unsealEventsResponse.html).
To learn more, see [example/unsealResult.mjs](./example/unsealResult.mjs) or the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/functions/unsealEventsResponse.html).
### Deleting visitor data
Customers on the Enterprise plan can [Delete all data associated with a specific visitor](https://dev.fingerprint.com/reference/deletevisitordata) to comply with privacy regulations. See [example/deleteVisitorData.mjs](./example/deleteVisitorData.mjs) or the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-node-sdk/docs/classes/FingerprintJsServerApiClient.html#deleteVisitorData).
Customers on the Enterprise plan can [Delete all data associated with a specific visitor](https://dev.fingerprint.com/reference/deletevisitordata) to comply with privacy regulations. See [example/deleteVisitor.mjs](./example/deleteVisitor.mjs) or the [API Reference](https://fingerprintjs.github.io/fingerprintjs-pro-server-api-node-sdk/classes/FingerprintJsServerApiClient.html#deleteVisitorData).

@@ -180,0 +229,0 @@ ## API Reference

@@ -11,3 +11,3 @@ /**

* @description Get a detailed analysis of an individual identification event, including Smart Signals.
* **Only for Enterprise customers:** Please note that the response includes mobile signals (e.g. `rootApps`) even if the request originated from a non-mobile platform.
* Please note that the response includes mobile signals (e.g. `rootApps`) even if the request originated from a non-mobile platform.
* It is highly recommended that you **ignore** the mobile signals for such requests.

@@ -38,3 +38,3 @@ *

*
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to activate it for you. Otherwise, you will receive a 403.
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403.
*/

@@ -210,4 +210,4 @@ delete: operations['deleteVisitorData']

}
ErrorVisitsDelete404Response: {
/** ErrorVisitsDelete404ResponseError */
ErrorVisitor404Response: {
/** ErrorVisitor404ResponseError */
error?: {

@@ -225,3 +225,3 @@ /**

}
ErrorVisitsDelete400Response: {
ErrorVisitor400Response: {
error?: {

@@ -267,2 +267,5 @@ /**

suspectScore?: components['schemas']['SuspectScoreResult']
remoteControl?: components['schemas']['RemoteControlResult']
velocity?: components['schemas']['VelocityResult']
developerTools?: components['schemas']['DeveloperToolsResult']
/**

@@ -321,3 +324,3 @@ * @description Unique identifier of the user's identification request.

/** @description A customer-provided value or an object that was sent with identification request. */
tag: {
tag?: {
[key: string]: unknown

@@ -393,3 +396,3 @@ }

/** @description A customer-provided value or an object that was sent with identification request. */
tag: {
tag?: {
[key: string]: unknown

@@ -701,2 +704,17 @@ }

}
/** SignalResponseRemoteControl */
remoteControl?: {
data?: components['schemas']['RemoteControlResult']
error?: components['schemas']['ProductError']
}
/** SignalResponseVelocity */
velocity?: {
data?: components['schemas']['VelocityResult']
error?: components['schemas']['ProductError']
}
/** SignalResponseDeveloperTools */
developerTools?: {
data?: components['schemas']['DeveloperToolsResult']
error?: components['schemas']['ProductError']
}
}

@@ -886,2 +904,13 @@ /** @description Contains results from all activated products - Fingerprint Pro, Bot Detection, and others. */

/**
* @description Sums key data points for a specific `visitorId` at three distinct time intervals: 5 minutes, 1 hour, and 24 hours as follows:
* - Number of identification events attributed to the visitor ID - Number of distinct IP addresses associated to the visitor ID. - Number of distinct countries associated with the visitor ID. - Number of distinct `linkedId`s associated with the visitor ID.
* The `24h` interval of `distinctIp`, `distinctLinkedId`, and `distinctCountry` will be omitted if the number of `events` for the visitor ID in the last 24 hours (`events.intervals.['24h']`) is higher than 20.000.
*/
VelocityResult: {
distinctIp: components['schemas']['VelocityIntervals']
distinctLinkedId: components['schemas']['VelocityIntervals']
distinctCountry: components['schemas']['VelocityIntervals']
events: components['schemas']['VelocityIntervals']
}
/**
* @description It includes 35+ raw browser identification attributes to provide Fingerprint users with even more information than our standard visitor ID provides. This enables Fingerprint users to not have to run our open-source product in conjunction with Fingerprint Pro Plus and Enterprise to get those additional attributes.

@@ -905,5 +934,6 @@ * Warning: The raw signals data can change at any moment as we improve the product. We cannot guarantee the internal shape of raw device attributes to be stable, so typical semantic versioning rules do not apply here. Use this data with caution without assuming a specific structure beyond the generic type provided here.

/**
* Time
* Format: date-time
* @description Time in UTC when the most recent factory reset of the Android or iOS device was done. If there is no sign of factory reset or the client is not a mobile device, the field will contain the epoch time (1 January 1970) in UTC.
* @description Indicates the time (in UTC) of the most recent factory reset that happened on the **mobile device**.
* When a factory reset cannot be detected on the mobile device or when the request is initiated from a browser, this field will correspond to the *epoch* time (i.e 1 Jan 1970 UTC).
* See [Factory Reset Detection](https://dev.fingerprint.com/docs/smart-signals-overview#factory-reset-detection) to learn more about this Smart Signal.
*

@@ -915,3 +945,5 @@ * @example 2022-06-09T22:58:36Z

* Format: int64
* @description Same value as it's in the `time` field but represented in timestamp format.
* @description This field is just another representation of the value in the `time` field.
* The time of the most recent factory reset that happened on the **mobile device** is expressed as Unix epoch time.
*
* @example 1654815517198

@@ -1014,2 +1046,34 @@ */

}
RemoteControlResult: {
/**
* @description `true` if the request came from a machine being remotely controlled (e.g. TeamViewer), `false` otherwise.
*
* @example false
*/
result: boolean
}
DeveloperToolsResult: {
/**
* @description `true` if the browser is Chrome with DevTools open or Firefox with Developer Tools open, `false` otherwise.
*
* @example false
*/
result: boolean
}
VelocityIntervals: {
intervals?: components['schemas']['VelocityIntervalResult']
}
/** @description Is absent if the velocity data could not be generated for the visitor ID. */
VelocityIntervalResult: {
/** @example 1 */
'5m': number
/** @example 1 */
'1h': number
/**
* @description The `24h` interval of `distinctIp`, `distinctLinkedId`, and `distinctCountry` will be omitted if the number of `events`` for the visitor ID in the last 24 hours (`events.intervals.['24h']`) is higher than 20.000.
*
* @example 1
*/
'24h'?: number
}
}

@@ -1031,3 +1095,3 @@ responses: never

* @description Get a detailed analysis of an individual identification event, including Smart Signals.
* **Only for Enterprise customers:** Please note that the response includes mobile signals (e.g. `rootApps`) even if the request originated from a non-mobile platform.
* Please note that the response includes mobile signals (e.g. `rootApps`) even if the request originated from a non-mobile platform.
* It is highly recommended that you **ignore** the mobile signals for such requests.

@@ -1151,3 +1215,3 @@ *

*
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to activate it for you. Otherwise, you will receive a 403.
* If you are interested in using this API, please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403.
*/

@@ -1169,3 +1233,3 @@ deleteVisitorData: {

content: {
'application/json': components['schemas']['ErrorVisitsDelete400Response']
'application/json': components['schemas']['ErrorVisitor400Response']
}

@@ -1182,3 +1246,3 @@ }

content: {
'application/json': components['schemas']['ErrorVisitsDelete404Response']
'application/json': components['schemas']['ErrorVisitor404Response']
}

@@ -1185,0 +1249,0 @@ }

@@ -7,1 +7,2 @@ export * from './urlUtils'

export * from './webhook'
export * from './errors/apiErrors'

@@ -1,3 +0,10 @@

export function copyResponseJson(response: Response) {
return response.clone().json()
import { SdkError } from './errors/apiErrors'
import { toError } from './utils'
export async function copyResponseJson(response: Response) {
try {
return await response.clone().json()
} catch (e) {
throw new SdkError('Failed to parse JSON response', response, toError(e))
}
}
import { getDeleteVisitorDataUrl, getEventUrl, getVisitorsUrl } from './urlUtils'
import { AuthenticationMode, EventResponse, Options, Region, VisitorHistoryFilter, VisitorsResponse } from './types'
import { copyResponseJson } from './responseUtils'
import {
AuthenticationMode,
ApiError,
CommonError429,
DeleteVisitorError,
EventError,
EventResponse,
isDeleteVisitorError,
isEventError,
isVisitorsError,
Options,
Region,
VisitorHistoryFilter,
VisitorsError,
DeleteVisit400Error,
DeleteVisit403Error,
DeleteVisit404Error,
EventError403,
EventError404,
VisitorsError403,
VisitorsError429,
VisitorsResponse,
} from './types'
import { copyResponseJson } from './responseUtils'
} from './errors/apiErrors'

@@ -63,3 +59,3 @@ export class FingerprintJsServerApiClient {

* console.log(err.response)
* console.log(`error ${err.status}: `, err.error?.message)
* console.log(`error ${err.statusCode}: `, err.message)
* } else {

@@ -83,24 +79,23 @@ * console.log('unknown error: ', err)

return this.fetch(url, {
const response = await this.fetch(url, {
method: 'GET',
headers,
})
.then(async (response) => {
const jsonResponse = await copyResponseJson(response)
if (response.status !== 200) {
throw { ...jsonResponse, response, status: response.status } as EventError
}
return jsonResponse as EventResponse
})
.catch((err: Error) => {
if (isEventError(err)) {
throw err
}
const jsonResponse = await copyResponseJson(response)
throw {
status: 0,
error: err,
}
})
if (response.status === 200) {
return jsonResponse as EventResponse
}
switch (response.status) {
case 403:
throw new EventError403(jsonResponse, response)
case 404:
throw new EventError404(jsonResponse, response)
default:
throw ApiError.unknown(response)
}
}

@@ -127,3 +122,3 @@

* if (isDeleteVisitorError(error)) {
* console.log(error.status, error.error)
* console.log(error.statusCode, error.message)
* }

@@ -145,33 +140,29 @@ * })

await this.fetch(url, {
const response = await this.fetch(url, {
method: 'DELETE',
headers,
})
.then(async (response) => {
if (response.status === 200) {
return
}
const jsonResponse = await copyResponseJson(response)
if (response.status === 200) {
return
}
if (response.status === 429) {
const retryAfter = this.getRetryAfter(response)
const jsonResponse = await copyResponseJson(response)
;(jsonResponse as CommonError429).retryAfter = retryAfter
? parseInt(retryAfter)
: FingerprintJsServerApiClient.DEFAULT_RETRY_AFTER
}
switch (response.status) {
case 429:
throw new CommonError429(jsonResponse, response)
throw { ...(jsonResponse as DeleteVisitorError), response, status: response.status } as DeleteVisitorError
})
.catch((err) => {
if (isDeleteVisitorError(err)) {
throw err
}
case 404:
throw new DeleteVisit404Error(jsonResponse, response)
throw {
status: 0,
error: err,
}
})
case 403:
throw new DeleteVisit403Error(jsonResponse, response)
case 400:
throw new DeleteVisit400Error(jsonResponse, response)
default:
throw ApiError.unknown(response)
}
}

@@ -202,3 +193,3 @@

* if (isVisitorsError(error)) {
* console.log(error.status, error.error)
* console.log(error.statusCode, error.message)
* if (error.status === 429) {

@@ -222,29 +213,23 @@ * retryLater(error.retryAfter) // Needs to be implemented on your side

return this.fetch(url, {
const response = await this.fetch(url, {
method: 'GET',
headers,
})
.then(async (response) => {
const jsonResponse = await copyResponseJson(response)
if (response.status === 200) {
return jsonResponse as VisitorsResponse
}
if (response.status === 429) {
const retryAfter = this.getRetryAfter(response)
;(jsonResponse as VisitorsError429).retryAfter = retryAfter
? parseInt(retryAfter)
: FingerprintJsServerApiClient.DEFAULT_RETRY_AFTER
}
throw { ...(jsonResponse as VisitorsError), response, status: response.status } as VisitorsError
})
.catch((err) => {
if (isVisitorsError(err)) {
throw err
}
throw {
status: 0,
error: err,
}
})
const jsonResponse = await copyResponseJson(response)
if (response.status === 200) {
return jsonResponse as VisitorsResponse
}
switch (response.status) {
case 403:
throw new VisitorsError403(jsonResponse, response)
case 429:
throw new VisitorsError429(jsonResponse, response)
default:
throw ApiError.unknown(response)
}
}

@@ -255,6 +240,2 @@

}
private getRetryAfter(response: Response) {
return response.headers.get('retry-after')
}
}

@@ -55,20 +55,16 @@ import { components, paths } from './generatedApiTypes'

export type VisitorsResponse = paths['/visitors/{visitor_id}']['get']['responses']['200']['content']['application/json']
export type VisitorsError403 =
export type VisitorsResponse403 =
paths['/visitors/{visitor_id}']['get']['responses']['403']['content']['application/json'] & {
status: 403
}
export type VisitorsError429 =
paths['/visitors/{visitor_id}']['get']['responses']['429']['content']['application/json'] & TooManyRequestsError
export type VisitorsResponse429 =
paths['/visitors/{visitor_id}']['get']['responses']['429']['content']['application/json']
export type DeleteVisitError404 =
paths['/visitors/{visitor_id}']['delete']['responses']['404']['content']['application/json'] & {
status: 404
}
export type DeleteVisit404Response =
paths['/visitors/{visitor_id}']['delete']['responses']['404']['content']['application/json']
export type DeleteVisitError403 =
paths['/visitors/{visitor_id}']['delete']['responses']['403']['content']['application/json'] & {
status: 403
}
export type DeleteVisit403Response =
paths['/visitors/{visitor_id}']['delete']['responses']['403']['content']['application/json']
export type DeleteVisitError400 =
export type DeleteVisit400Response =
paths['/visitors/{visitor_id}']['delete']['responses']['400']['content']['application/json'] & {

@@ -78,36 +74,9 @@ status: 400

export type CommonError429 = components['schemas']['ErrorCommon429Response'] & TooManyRequestsError
export type CommonResponse429 = components['schemas']['ErrorCommon429Response']
export type VisitorsError = WithResponse<VisitorsError403 | VisitorsError429>
export type VisitorsError = WithResponse<VisitorsResponse403 | VisitorsResponse429>
export type DeleteVisitorError = WithResponse<
DeleteVisitError404 | DeleteVisitError403 | DeleteVisitError400 | CommonError429
>
export function isVisitorsError(response: any): response is VisitorsError {
return (
(response?.hasOwnProperty('status') &&
(response.status === 403 || response.status === 429) &&
response?.hasOwnProperty('error') &&
typeof response.error === 'string') ||
false
)
}
export function isDeleteVisitorError(response: any): response is DeleteVisitorError {
const statusCodes = [400, 403, 404, 429]
return Boolean(
response?.hasOwnProperty('status') &&
statusCodes.includes(response.status) &&
response.error?.hasOwnProperty('message') &&
typeof response.error.message === 'string' &&
response.error?.hasOwnProperty('code') &&
typeof response.error.code === 'string'
)
}
export type EventResponse = paths['/events/{request_id}']['get']['responses']['200']['content']['application/json']
export type EventError403 = paths['/events/{request_id}']['get']['responses']['403']['content']['application/json']
export type EventError404 = paths['/events/{request_id}']['get']['responses']['404']['content']['application/json']
export type EventResponse403 = paths['/events/{request_id}']['get']['responses']['403']['content']['application/json']
export type EventResponse404 = paths['/events/{request_id}']['get']['responses']['404']['content']['application/json']

@@ -118,24 +87,2 @@ type WithResponse<T> = T & {

type GenericEventError = WithResponse<EventError403 | EventError404>
type EventErrorCode<T extends GenericEventError> = T extends EventError403 ? 403 : 404
export type EventError<T extends GenericEventError = GenericEventError> = WithResponse<
T & {
status: EventErrorCode<T>
}
>
export function isEventError(response: any): response is EventError {
return (
(response?.hasOwnProperty('status') &&
(response.status === 403 || response.status === 404) &&
response?.hasOwnProperty('error') &&
response.error?.hasOwnProperty('message') &&
typeof response.error.message === 'string' &&
response.error?.hasOwnProperty('code') &&
typeof response.error.code === 'string') ||
false
)
}
/**

@@ -142,0 +89,0 @@ * More info: https://dev.fingerprintjs.com/docs/webhooks#identification-webhook-object-format

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc