@fingerprintjs/fingerprintjs-pro-server-api
Advanced tools
Comparing version 4.1.2 to 5.0.0-test.1
{ | ||
"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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
219917
18
5295
235
2
3