fingerprintjs / BotD

Bot detection library that runs in the browser. Detects automation tools and frameworks. No server required, runs 100% on the client. MIT license, no usage restrictions.

Home Page:https://fingerprintjs.github.io/BotD/main/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Code review

Finesse opened this issue · comments

Hi, Valentin has asked me to do a code review of the project to make it more production ready.

Issues

Not minified distributive files

Since the project is open-source, you can publish not minified versions of the distributive files too. It will help library users debug the code.

Output the not minified files into the dist directory that gets published to NPM, and remove the minified files that aren't supposed to be used by browser: botd.cjs.min.js, botd.esm.min.js (don't remove it if you don't follow the "external dependencies" recommendation). See the FingerprintJS's Rollup configuration as an example.

Copyright banner in distributive files

Add a copyright comment to the start of every distributive file so that people who open the code knows what the code is and where to search for documentation. See an example at https://cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.min.js.

Excess items in the .d.ts

The dist/botd.d.ts file contains not documented items, BotDetector's attributes and methods, to be precise. As far as I understand, they are for internal usage only. Once you publish such .d.ts file to NPM, you'll have to keep these attributes in methods working until you release a new major version.

A good way to fix it is doing this replacement:

- export async function load(options: Options): Promise<BotDetector>
+ export async function load(options: Options): Promise<BotDetectorInterface>

Where BotDetectorInterface is a TypeScript interface that has only the attributes and methods designed for usage by external users.

More specific .d.ts

Instead of using string as the mode option type, create a new type that describes the exact values that the option supports.

Describe the exact type that detect and getResult return. It will be perfect if the file describes how the return type depends on the arguments like FingerprintJS Pro Agent does.

Add a type for errors thrown by the library, and a type with all expected error codes. Having such a type will help you to prevent mistakes in error codes.

Contribution instructions (will be fixed in #32)

If a person wants to make a pull request, they won't know how to run the project locally, how to test it, how to prepare for pull-requesting. Usually contributing.md holds such information.

Handling unexpected source errors

It's important to know when something unexpected happens. So, there should be a separate status for unexpected errors. Some sources in the code throw expected errors and the -1 status is used for expected errors. If you want to handle expected errors differently, you can create separate statuses for them.

"Source" naming

"Source" is a function that gets information about browsers. The source result is called "component".

Add comments to unobvious code

For example, why a Content-Type: text/plain header is added to the API request. It will help prevent regressions.

Wrong error handling documentation

The documentation that the following error type is thrown:

{
  "code": "TokenNotFound",
  "message": "token not found"
}

In fact, the following type is thrown:

{
  "error": {
    "code": "BotdFailed",
    "message": "Foo"
  }
}

Also, consider adding stack traces to unexpected errors, it will help you a lot.

Load time unexpected errors aren't converted to the described type.

getResult purpose (will be fixed in #32)

What's the use case of getResult? If it's supposed to be called on a consecutive visit, then collect will be called and it's result won't be used. Also, there is no way to decide what to call: detect or getResult.

If it's supposed to be called during the same page session, then there is no need to store it in cookies.

Why not to use local storage instead of cookies? It has a simple API and is more reliable.

The getResult method looks like something additional to bot detection, i.e. a part of a higher level product that uses Botd as a dependency. It can be a part of the same NPM package.

Recommendations (optional)

External dependencies

Make the distributive files designed to be used with bundlers like Webpack and Rollbar (ESM, CJS) import the dependencies instead of including the dependencies into the code. It will reduce the size of end users' code by de-duplicating the dependencies.

For example, if somebody makes a project with @fingerprintjs/fingerprintjs and @fpjs-incubator/botd-agent today, they will have 2 copies of tslib in their code. But if dist/botd.esm.js of @fpjs-incubator/botd-agent imports tslib instead of including it, there will be only 1 copy of tslib.

See the FingerprintJS's Rollup configuration to learn how to make a dependency be external.

Documentation in .d.ts (will be fixed in #32)

If you add comments to the functions, attributes and methods in dist/bot.d.ts, users will be able to get information about the JS API without leaving the IDE. It's a common practice. In order for IDEs to turn the comments into hints, they must start with /** and end with */, for example:

/**
 * An option for changing ...
 */

This is called JSDoc, it also supports tags such as @deprecated, you can learn more at https://jsdoc.app.

Screen Shot 2021-08-06 at 13 35 27

Room for options

Make a room for future options in detect by passing options in an objects instead of a plain list of arguments.

A single code style throughout the company

Use the same Prettier settings, and the same naming cases.

Browser support

Add a documentation section that tells what browsers the library supports. Make a BrowserStack test that checks that the library at least can run in these browsers. If it supports only modern browsers, adjust the target field of tsconfig.json to reduce the distributive code size.

Ideally, the whole code should be covered with automatic tests that run in different browsers on BrowserStack.

Turn the playground into a development playground

At the moment the playground runs the latest published version of the library. It can run the current local code instead, and therefore be a convenient tool for developing the library.

BTW the resources/favicon.ico file is not used.

Performance of individual sources

Consider measuring performance of each of the sources. It will let you know what sources tend to decrease the whole performance.

Avoid .then

Mixing await and then looks sloppy. For example, in the detect method of BotDetector.