Comparing version 1.0.0-alpha.5 to 1.0.0-alpha.6
@@ -1,4 +0,3 @@ | ||
import { ArcjetBotType, ArcjetEmailType, ArcjetMode, ArcjetStack, ArcjetDecision, ArcjetRule, ArcjetRequestDetails } from "@arcjet/protocol"; | ||
import { ArcjetContext, ArcjetBotType, ArcjetEmailType, ArcjetMode, ArcjetStack, ArcjetDecision, ArcjetRule, ArcjetRequestDetails } from "@arcjet/protocol"; | ||
import { Transport } from "@arcjet/protocol/proto.js"; | ||
import { Logger } from "@arcjet/logger"; | ||
export * from "@arcjet/protocol"; | ||
@@ -14,10 +13,5 @@ export type Simplify<T> = { | ||
Intersection & Union : never; | ||
export type RemoteClientContext = { | ||
key: string; | ||
fingerprint: string; | ||
log: Logger; | ||
}; | ||
export interface RemoteClient { | ||
decide(context: RemoteClientContext, details: Partial<ArcjetRequestDetails>, rules: ArcjetRule[]): Promise<ArcjetDecision>; | ||
report(context: RemoteClientContext, request: Partial<ArcjetRequestDetails>, decision: ArcjetDecision, rules: ArcjetRule[]): void; | ||
decide(context: ArcjetContext, details: Partial<ArcjetRequestDetails>, rules: ArcjetRule[]): Promise<ArcjetDecision>; | ||
report(context: ArcjetContext, request: Partial<ArcjetRequestDetails>, decision: ArcjetDecision, rules: ArcjetRule[]): void; | ||
} | ||
@@ -24,0 +18,0 @@ export type RemoteClientOptions = { |
62
index.js
@@ -73,5 +73,5 @@ import { ArcjetErrorDecision, ArcjetErrorReason, ArcjetRuleResult, ArcjetReason, ArcjetDenyDecision, ArcjetEmailReason, ArcjetBotType, ArcjetBotReason } from '@arcjet/protocol'; | ||
// in production so calls fail open. | ||
const timeout = options?.timeout ?? process.env["NODE_ENV"] === "production" ? 500 : 1000; | ||
const timeout = options?.timeout ?? (process.env["NODE_ENV"] === "production" ? 500 : 1000); | ||
const sdkStack = ArcjetStackToProtocol(options?.sdkStack ?? "NODEJS"); | ||
const sdkVersion = "1.0.0-alpha.5"; | ||
const sdkVersion = "1.0.0-alpha.6"; | ||
const client = createPromiseClient(DecideService, options.transport); | ||
@@ -99,2 +99,3 @@ return Object.freeze({ | ||
}); | ||
context.log.debug("Decide request to %s", baseUrl); | ||
const response = await client.decide(decideRequest, { | ||
@@ -104,3 +105,14 @@ headers: { Authorization: `Bearer ${context.key}` }, | ||
}); | ||
return ArcjetDecisionFromProtocol(response.decision); | ||
const decision = ArcjetDecisionFromProtocol(response.decision); | ||
context.log.debug("Decide response", { | ||
id: decision.id, | ||
fingerprint: context.fingerprint, | ||
path: details.path, | ||
runtime: runtime(), | ||
ttl: decision.ttl, | ||
conclusion: decision.conclusion, | ||
reason: decision.reason, | ||
ruleResults: decision.results, | ||
}); | ||
return decision; | ||
}, | ||
@@ -129,3 +141,3 @@ report(context, details, decision, rules) { | ||
}); | ||
context.log.debug("report: ", baseUrl); | ||
context.log.debug("Report request to %s", baseUrl); | ||
// We use the promise API directly to avoid returning a promise from this function so execution can't be paused with `await` | ||
@@ -135,4 +147,13 @@ client | ||
headers: { Authorization: `Bearer ${context.key}` }, | ||
timeoutMs: timeout, | ||
timeoutMs: 2000, // 2 seconds | ||
}) | ||
.then((response) => { | ||
context.log.debug("Report response", { | ||
id: response.decision?.id, | ||
fingerprint: context.fingerprint, | ||
path: details.path, | ||
runtime: runtime(), | ||
ttl: decision.ttl, | ||
}); | ||
}) | ||
.catch((err) => { | ||
@@ -273,6 +294,6 @@ context.log.log("Encountered problem sending report: %s", errorMessage(err)); | ||
allowDomainLiteral, | ||
validate(fingerprint, details) { | ||
validate(context, details) { | ||
assert(typeof details.email !== "undefined", "ValidateEmail requires `email` to be set."); | ||
}, | ||
async protect(fingerprint, { email }) { | ||
async protect(context, { email }) { | ||
if (await analyze.isValidEmail(email, analyzeOpts)) { | ||
@@ -325,3 +346,3 @@ return new ArcjetRuleResult({ | ||
remove, | ||
validate(fingerprint, details) { | ||
validate(context, details) { | ||
assert(typeof details.headers !== "undefined", "DetectBot requires `headers` to be set."); | ||
@@ -332,3 +353,3 @@ }, | ||
*/ | ||
async protect(fingerprint, { headers }) { | ||
async protect(context, { headers }) { | ||
const headersKV = {}; | ||
@@ -442,2 +463,3 @@ for (const [key, value] of headers) { | ||
log.timeEnd("fingerprint"); | ||
const context = { key, fingerprint, log }; | ||
if (flatSortedRules.length > 10) { | ||
@@ -452,3 +474,3 @@ log.error("Failure running rules. Only 10 rules may be specified."); | ||
}); | ||
client.report({ key, fingerprint, log }, details, decision, | ||
client.report(context, details, decision, | ||
// No rules because we've determined they were too long and we don't | ||
@@ -490,3 +512,3 @@ // want to try to send them to the server | ||
}); | ||
client.report({ key, fingerprint, log }, details, decision, flatSortedRules); | ||
client.report(context, details, decision, flatSortedRules); | ||
log.debug("decide: already blocked", { | ||
@@ -513,4 +535,4 @@ id: decision.id, | ||
try { | ||
localRule.validate(fingerprint, details); | ||
results[idx] = await localRule.protect(fingerprint, details); | ||
localRule.validate(context, details); | ||
results[idx] = await localRule.protect(context, details); | ||
log.debug("Local rule result:", { | ||
@@ -546,3 +568,3 @@ id: results[idx].ruleId, | ||
// request. | ||
client.report({ key, fingerprint, log }, details, decision, flatSortedRules); | ||
client.report(context, details, decision, flatSortedRules); | ||
// If we're not in DRY_RUN mode, we want to cache non-zero TTL results | ||
@@ -570,14 +592,4 @@ // and return this DENY decision. | ||
log.time("decideApi"); | ||
const decision = await client.decide({ key, fingerprint, log }, details, flatSortedRules); | ||
const decision = await client.decide(context, details, flatSortedRules); | ||
log.timeEnd("decideApi"); | ||
log.debug("remote rule result:", { | ||
id: decision.id, | ||
fingerprint, | ||
path: details.path, | ||
runtime: runtime(), | ||
ttl: decision.ttl, | ||
conclusion: decision.conclusion, | ||
reason: decision.reason, | ||
ruleResults: decision.results, | ||
}); | ||
// If the decision is to block and we have a non-zero TTL, we cache the | ||
@@ -584,0 +596,0 @@ // block locally |
109
index.ts
import { | ||
ArcjetContext, | ||
ArcjetBotReason, | ||
@@ -153,11 +154,5 @@ ArcjetBotType, | ||
export type RemoteClientContext = { | ||
key: string; | ||
fingerprint: string; | ||
log: Logger; | ||
}; | ||
export interface RemoteClient { | ||
decide( | ||
context: RemoteClientContext, | ||
context: ArcjetContext, | ||
details: Partial<ArcjetRequestDetails>, | ||
@@ -169,3 +164,3 @@ rules: ArcjetRule[], | ||
report( | ||
context: RemoteClientContext, | ||
context: ArcjetContext, | ||
request: Partial<ArcjetRequestDetails>, | ||
@@ -207,3 +202,3 @@ decision: ArcjetDecision, | ||
const timeout = | ||
options?.timeout ?? process.env["NODE_ENV"] === "production" ? 500 : 1000; | ||
options?.timeout ?? (process.env["NODE_ENV"] === "production" ? 500 : 1000); | ||
@@ -217,3 +212,3 @@ const sdkStack = ArcjetStackToProtocol(options?.sdkStack ?? "NODEJS"); | ||
async decide( | ||
context: RemoteClientContext, | ||
context: ArcjetContext, | ||
details: ArcjetRequestDetails, | ||
@@ -242,2 +237,4 @@ rules: ArcjetRule[], | ||
context.log.debug("Decide request to %s", baseUrl); | ||
const response = await client.decide(decideRequest, { | ||
@@ -248,7 +245,20 @@ headers: { Authorization: `Bearer ${context.key}` }, | ||
return ArcjetDecisionFromProtocol(response.decision); | ||
const decision = ArcjetDecisionFromProtocol(response.decision); | ||
context.log.debug("Decide response", { | ||
id: decision.id, | ||
fingerprint: context.fingerprint, | ||
path: details.path, | ||
runtime: runtime(), | ||
ttl: decision.ttl, | ||
conclusion: decision.conclusion, | ||
reason: decision.reason, | ||
ruleResults: decision.results, | ||
}); | ||
return decision; | ||
}, | ||
report( | ||
context: RemoteClientContext, | ||
context: ArcjetContext, | ||
details: ArcjetRequestDetails, | ||
@@ -280,3 +290,3 @@ decision: ArcjetDecision, | ||
context.log.debug("report: ", baseUrl); | ||
context.log.debug("Report request to %s", baseUrl); | ||
@@ -287,4 +297,13 @@ // We use the promise API directly to avoid returning a promise from this function so execution can't be paused with `await` | ||
headers: { Authorization: `Bearer ${context.key}` }, | ||
timeoutMs: timeout, | ||
timeoutMs: 2_000, // 2 seconds | ||
}) | ||
.then((response) => { | ||
context.log.debug("Report response", { | ||
id: response.decision?.id, | ||
fingerprint: context.fingerprint, | ||
path: details.path, | ||
runtime: runtime(), | ||
ttl: decision.ttl, | ||
}); | ||
}) | ||
.catch((err: unknown) => { | ||
@@ -550,3 +569,3 @@ context.log.log( | ||
validate( | ||
fingerprint: string, | ||
context: ArcjetContext, | ||
details: Partial<ArcjetRequestDetails & { email: string }>, | ||
@@ -561,3 +580,3 @@ ): asserts details is ArcjetRequestDetails & { email: string } { | ||
async protect( | ||
fingerprint: string, | ||
context: ArcjetContext, | ||
{ email }: ArcjetRequestDetails & { email: string }, | ||
@@ -620,3 +639,3 @@ ): Promise<ArcjetRuleResult> { | ||
validate( | ||
fingerprint: string, | ||
context: ArcjetContext, | ||
details: Partial<ArcjetRequestDetails>, | ||
@@ -634,3 +653,3 @@ ): asserts details is ArcjetRequestDetails { | ||
async protect( | ||
fingerprint: string, | ||
context: ArcjetContext, | ||
{ headers }: ArcjetRequestDetails, | ||
@@ -820,2 +839,4 @@ ): Promise<ArcjetRuleResult> { | ||
const context: ArcjetContext = { key, fingerprint, log }; | ||
if (flatSortedRules.length > 10) { | ||
@@ -833,3 +854,3 @@ log.error("Failure running rules. Only 10 rules may be specified."); | ||
client.report( | ||
{ key, fingerprint, log }, | ||
context, | ||
details, | ||
@@ -879,8 +900,3 @@ decision, | ||
client.report( | ||
{ key, fingerprint, log }, | ||
details, | ||
decision, | ||
flatSortedRules, | ||
); | ||
client.report(context, details, decision, flatSortedRules); | ||
@@ -911,4 +927,4 @@ log.debug("decide: already blocked", { | ||
try { | ||
localRule.validate(fingerprint, details); | ||
results[idx] = await localRule.protect(fingerprint, details); | ||
localRule.validate(context, details); | ||
results[idx] = await localRule.protect(context, details); | ||
@@ -953,8 +969,3 @@ log.debug("Local rule result:", { | ||
// request. | ||
client.report( | ||
{ key, fingerprint, log }, | ||
details, | ||
decision, | ||
flatSortedRules, | ||
); | ||
client.report(context, details, decision, flatSortedRules); | ||
@@ -971,7 +982,3 @@ // If we're not in DRY_RUN mode, we want to cache non-zero TTL results | ||
blockCache.set( | ||
fingerprint, | ||
decision.reason, | ||
decision.ttl, | ||
); | ||
blockCache.set(fingerprint, decision.reason, decision.ttl); | ||
} | ||
@@ -997,30 +1004,14 @@ | ||
log.time("decideApi"); | ||
const decision = await client.decide( | ||
{ key, fingerprint, log }, | ||
details, | ||
flatSortedRules, | ||
); | ||
const decision = await client.decide(context, details, flatSortedRules); | ||
log.timeEnd("decideApi"); | ||
log.debug("remote rule result:", { | ||
id: decision.id, | ||
fingerprint, | ||
path: details.path, | ||
runtime: runtime(), | ||
ttl: decision.ttl, | ||
conclusion: decision.conclusion, | ||
reason: decision.reason, | ||
ruleResults: decision.results, | ||
}); | ||
// If the decision is to block and we have a non-zero TTL, we cache the | ||
// block locally | ||
if (decision.isDenied() && decision.ttl > 0) { | ||
log.debug("decide: Caching block locally for %d milliseconds", decision.ttl); | ||
blockCache.set( | ||
fingerprint, | ||
decision.reason, | ||
log.debug( | ||
"decide: Caching block locally for %d milliseconds", | ||
decision.ttl, | ||
); | ||
blockCache.set(fingerprint, decision.reason, decision.ttl); | ||
} | ||
@@ -1027,0 +1018,0 @@ |
{ | ||
"name": "arcjet", | ||
"version": "1.0.0-alpha.5", | ||
"version": "1.0.0-alpha.6", | ||
"description": "Arcjet TypeScript and JavaScript SDK core", | ||
@@ -34,13 +34,13 @@ "license": "Apache-2.0", | ||
"dependencies": { | ||
"@arcjet/analyze": "1.0.0-alpha.5", | ||
"@arcjet/logger": "1.0.0-alpha.5", | ||
"@arcjet/protocol": "1.0.0-alpha.5" | ||
"@arcjet/analyze": "1.0.0-alpha.6", | ||
"@arcjet/logger": "1.0.0-alpha.6", | ||
"@arcjet/protocol": "1.0.0-alpha.6" | ||
}, | ||
"devDependencies": { | ||
"@arcjet/eslint-config": "1.0.0-alpha.5", | ||
"@arcjet/rollup-config": "1.0.0-alpha.5", | ||
"@arcjet/tsconfig": "1.0.0-alpha.5", | ||
"@arcjet/eslint-config": "1.0.0-alpha.6", | ||
"@arcjet/rollup-config": "1.0.0-alpha.6", | ||
"@arcjet/tsconfig": "1.0.0-alpha.6", | ||
"@edge-runtime/jest-environment": "2.3.7", | ||
"@jest/globals": "29.7.0", | ||
"@rollup/wasm-node": "4.8.0", | ||
"@rollup/wasm-node": "4.9.0", | ||
"@types/node": "18.18.0", | ||
@@ -47,0 +47,0 @@ "jest": "29.7.0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
78420
1705
+ Added@arcjet/analyze@1.0.0-alpha.6(transitive)
+ Added@arcjet/logger@1.0.0-alpha.6(transitive)
+ Added@arcjet/protocol@1.0.0-alpha.6(transitive)
+ Added@connectrpc/connect@1.2.0(transitive)
- Removed@arcjet/analyze@1.0.0-alpha.5(transitive)
- Removed@arcjet/logger@1.0.0-alpha.5(transitive)
- Removed@arcjet/protocol@1.0.0-alpha.5(transitive)
- Removed@connectrpc/connect@1.1.4(transitive)
Updated@arcjet/logger@1.0.0-alpha.6