release: WRNexusJS 0.5.0

This commit is contained in:
2026-07-29 12:51:10 +05:30
parent 76c768099d
commit 6afe32f63f
456 changed files with 40879 additions and 8850 deletions
+33
View File
@@ -73,11 +73,44 @@ function defaultFailure(options: CaptchaGuardOptions, result: CaptchaVerificatio
}
export function captchaGuard(options: CaptchaGuardOptions) {
const verifiedForMs = options.verifiedForMs ?? 0;
if (!Number.isFinite(verifiedForMs) || verifiedForMs < 0) {
throw new TypeError("captchaGuard verifiedForMs must be a non-negative finite duration");
}
const sessionKey = options.sessionKey ?? "wrnexus.captcha.grants";
return async (ctx: Context, next: () => Promise<Response> | Response): Promise<Response> => {
const action = resolveAction(options.action, ctx);
const now = Date.now();
const grants = ctx.session.get<CaptchaSessionGrant[]>(sessionKey) ?? [];
const grant = verifiedForMs > 0 ? validCaptchaGrant(grants, action, now) : undefined;
if (grant) {
ctx.locals.captcha = {
success: true,
provider: grant.provider,
action,
};
ctx.locals.captchaVerified = true;
return next();
}
const result = await verifyRequest(ctx, options);
ctx.locals.captcha = result;
if (!result.success)
return options.onFailure ? options.onFailure(ctx, result) : defaultFailure(options, result);
if (verifiedForMs > 0) {
const fresh: CaptchaSessionGrant = {
action,
provider: result.provider,
expiresAt: now + verifiedForMs,
};
ctx.session.set(sessionKey, [
...grants.filter((item) => item.expiresAt > now && item.action !== action),
fresh,
]);
}
return next();
};
}
+9 -1
View File
@@ -313,6 +313,15 @@ export interface CaptchaGuardOptions {
responseField?: string;
provider?: CaptchaProvider;
engine?: CaptchaEngine;
/**
* Keep successful verification bound to the current session and action for
* this duration. Useful for retryable operations such as login, where a
* valid CAPTCHA should not be repeated after an unrelated credential error.
* Defaults to 0 (every request needs its own response token).
*/
verifiedForMs?: number;
/** Session key used for verified grants. */
sessionKey?: string;
failureStatus?: number;
failureMessage?: string;
bindHostname?: boolean;
@@ -325,7 +334,6 @@ export interface CaptchaPageGateOptions extends CaptchaGuardOptions {
policy?: CaptchaPolicyOptions;
challengePath?: string;
returnToParam?: string;
sessionKey?: string;
signals?: (ctx: Context) => CaptchaRiskSignals | Promise<CaptchaRiskSignals>;
}