arcjet / arcjet-js

Arcjet JS SDKs. Bot detection, rate limiting, email validation, attack protection, data redaction for Node.js, Next.js, Deno, Bun, SvelteKit, NestJS.
https://arcjet.com
Apache License 2.0
267 stars 7 forks source link

Remove ability to construct multiple rules with one constructor #1397

Closed blaine-arcjet closed 1 month ago

blaine-arcjet commented 2 months ago

Currently, all of our rules are designed to iterate over all options arguments and generate an array of rules. For example:

let rules = shield({ mode: "DRY_RUN" }, { mode: "LIVE" }, { mode: "DRY_RUN" })
// rules === [shieldRule1, shieldRule2, shieldRule3]

This feature was added after some feedback from the team that they wanted to construct multiple rules with one constructor; however, the same can be achieved with the following example:

let rules = [
    shield({ mode: "DRY_RUN" }),
    shield({ mode: "LIVE" }),
    shield({ mode: "DRY_RUN" }),
];
// More or less because we flatten nested arrays
// rules === [shieldRule1, shieldRule2, shieldRule3]

Supporting the first example is a place for bugs to sneak in because we might not be accessing the right options (such as highlighted in https://github.com/arcjet/arcjet-js/pull/1300#discussion_r1727832962) and it has become less useful for some rules that do type inference. For example, you can't construct multiple sensitiveInfo rules with detect functions having different type signatures due to said inference.

Additionally, I don't believe this feature is documented anywhere and we always demonstrate using the rule constructor to build a single rule.

Note: This is different than "Products" and only applies to multiple arguments passed to a single "Primitive" constructor. "Products" still need to return an array of multiple rules, as they generally combine multiple rules configured together.