-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore!: deprecate reason
for ArcjetAllowDecision
#2715
base: main
Are you sure you want to change the base?
Conversation
Merging to
|
Can you add the migration example code to this PR description please? It should be documented in the changelog as well, but it'll be helpful to have it in this PR in case someone comes across it. |
252d92f
to
8b78916
Compare
reason
for ArcjetAllowDecision
reason
for ArcjetAllowDecision
decorate/index.ts
Outdated
@@ -208,7 +208,7 @@ export function setRateLimitHeaders( | |||
.sort(sortByLowestMax) | |||
.map(toPolicyString) | |||
.join(", "); | |||
} else { | |||
} else if (typeof decision.reason !== "undefined") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why doesn't isRateLimitReason
just taking an optional reason?
protocol/index.ts
Outdated
@@ -591,7 +591,7 @@ export abstract class ArcjetDecision { | |||
ip: ArcjetIpDetails; | |||
|
|||
abstract conclusion: ArcjetConclusion; | |||
abstract reason: ArcjetReason; | |||
abstract reason: ArcjetReason | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stinks. We might want to remove these abstract fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They could be useful if someone wants to type-check on a generic ArcjetDecision to see if it has a reason or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to double check, but I don't think this needs to be abstract to do that.
protocol/index.ts
Outdated
export type ArcjetDecisionWithReason = ArcjetDecision & { | ||
reason: NonNullable<ArcjetDecision["reason"]>; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you not like its existence, or just how its defined?
I could change it to just ArcjetDecision & { reason: ArcjetReason}
, or else we'd have to use that definition in every function that requires a reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to provide it because they could write their own intersection. Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah they could! I've removed it
const policies = new Map<number, number>(); | ||
for (const reason of rateLimitReasons) { | ||
if (policies.has(reason.max)) { | ||
console.error( | ||
"Invalid rate limit policy—two policies should not share the same limit", | ||
); | ||
} | ||
|
||
if ( | ||
typeof reason.max !== "number" || | ||
typeof reason.window !== "number" || | ||
typeof reason.remaining !== "number" || | ||
typeof reason.reset !== "number" | ||
) { | ||
console.error(format("Invalid rate limit encountered: %o", reason)); | ||
} | ||
|
||
policies.set(reason.max, reason.window); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Policies isn't doing anything? Did you want to break out of the logic or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its used to print an error if two rate limit policies share the same limit, like we do in decorate. The difference is that decorate returns an error in this case. We could respond with a 500 here to have the same behavior. What do you think?
Another option would be to detect invalid configs earlier, such as when initializing Arcjet. But that would be a much larger change.
@@ -10,6 +10,7 @@ | |||
}, | |||
"dependencies": { | |||
"@arcjet/next": "file:../../arcjet-next", | |||
"@arcjet/sprintf": "file:../../sprintf", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might not be needed if you don't keep the policies stuff
console.error(format("Invalid rate limit encountered: %o", reason)); | ||
} | ||
|
||
policies.set(reason.max, reason.window); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
examples/nextjs-openai/package.json
Outdated
@@ -11,6 +11,7 @@ | |||
"dependencies": { | |||
"@ai-sdk/openai": "^1.0.8", | |||
"@arcjet/next": "file:../../arcjet-next", | |||
"@arcjet/sprintf": "file:../../sprintf", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
protocol/index.ts
Outdated
export type ArcjetDecisionWithReason = ArcjetDecision & { | ||
reason: NonNullable<ArcjetDecision["reason"]>; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to provide it because they could write their own intersection. Right?
{ status: 403, headers }, | ||
); | ||
} | ||
const allowedBots = decision.results.reduce<string[]>(reduceAllowedBots, []); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed you are still using map/filter in the other examples (for rate limit). We should keep it uniform. The reason to use a reduce is to avoid creating extra arrays, but the implementation of the reduction function is creating a new array on each iteration which is worse than a single filter then a map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed this to a reduce. This removes checking that a limit isn't duplicated which is discussed in another comment though.
protocol/client.ts
Outdated
@@ -127,7 +128,7 @@ export function createClient(options: ClientOptions): Client { | |||
report( | |||
context: ArcjetContext, | |||
details: ArcjetRequestDetails, | |||
decision: ArcjetDecision, | |||
decision: ArcjetDecisionWithReason, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't need to have a reason, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happened with also deprecating reason
on ArcjetErrorDecision?
protocol/index.ts
Outdated
export class ArcjetAllowDecision extends ArcjetDecision { | ||
conclusion = "ALLOW" as const; | ||
reason: ArcjetReason; | ||
/** @deprecated */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a message
protocol/index.ts
Outdated
@@ -591,7 +591,7 @@ export abstract class ArcjetDecision { | |||
ip: ArcjetIpDetails; | |||
|
|||
abstract conclusion: ArcjetConclusion; | |||
abstract reason: ArcjetReason; | |||
abstract reason: ArcjetReason | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to double check, but I don't think this needs to be abstract to do that.
…2855) While reviewing #2715 locally, I noticed that `/** @deprecated */` wasn't being marked in my editor. This is because `/** */` is just a block comment and not a doc comment. Doc comments need to be in the form as I've changed this PR. Additionally, deprecating the top-level export didn't seem to mark anything in the editor, so each field needed to be marked as deprecated. Furthermore, overriding the type as `ArcjetEnum<>` seemed to lose the doc comments. I also removed the exports locally and made everything compile once they are removed. They still exist for now but I want the removal to be seamless.
Converting to draft while we discuss this further. |
This PR makes
reason
optional forArcjetAllowDecision
and deprecates it.We are making this change because the rule that is accessible through the
reason
field is not obvious to our users and has the potential to cause confusion.Instead we recommend iterating through the
ruleResults
list to find rule you are looking for.