🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@arcjet/analyze

Package Overview
Dependencies
Maintainers
2
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arcjet/analyze - npm Package Compare versions

Comparing version
1.6.1
to
1.7.0-rc.0
+133
dist/index.d.ts
import { BotConfig, BotResult, DetectSensitiveInfoFunction, DetectedSensitiveInfoEntity, EmailValidationConfig, EmailValidationResult, FilterResult, SensitiveInfoEntities, SensitiveInfoEntity, SensitiveInfoResult } from "@arcjet/analyze-wasm";
import { ArcjetLogger } from "@arcjet/protocol";
//#region src/index.d.ts
interface AnalyzeContext {
log: ArcjetLogger;
characteristics: string[];
}
/**
* Request passed as a JSON string into WebAssembly.
*
* This is like `ArcjetRequestDetails` from `@arcjet/protocol`,
* but fields are often optional across the boundary.
*/
interface AnalyzeRequest {
/**
* IP address (IPv4 or IPv6).
*/
ip?: string | undefined;
/**
* HTTP method (such as `GET`).
*/
method?: string | undefined;
/**
* Protocol (such as `"http:"`).
*/
protocol?: string | undefined;
/**
* Hostname (such as `"example.com"`).
*/
host?: string | undefined;
/**
* Path (such as `"/path/to/resource"`).
*/
path?: string | undefined;
/**
* Headers of the request.
*/
headers?: Record<string, string> | undefined;
/**
* Cookies of the request (such as `"cookie1=value1; cookie2=value2"`).
*/
cookies?: string | undefined;
/**
* Query string of the request (such as `"?q=alpha"`).
*/
query?: string | undefined;
/**
* Extra info.
*/
extra?: Record<string, string> | undefined;
}
/**
* Generate a fingerprint.
*
* Fingerprints can be used to identify the client across multiple requests.
*
* This considers different things on the `request` based on the passed
* `context.characteristics`.
*
* See [*Fingerprints* on
* `docs.arcjet.com`](https://docs.arcjet.com/fingerprints/) for more info.
*
* @param context
* Context.
* @param request
* Request.
* @returns
* Promise for a SHA-256 fingerprint.
*/
declare function generateFingerprint(context: AnalyzeContext, request: AnalyzeRequest): Promise<string>;
/**
* Check whether an email is valid.
*
* @param context
* Context.
* @param value
* Value.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
declare function isValidEmail(context: AnalyzeContext, value: string, options: EmailValidationConfig): Promise<EmailValidationResult>;
/**
* Detect whether a request is by a bot.
*
* @param context
* Context.
* @param request
* Request.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
declare function detectBot(context: AnalyzeContext, request: AnalyzeRequest, options: BotConfig): Promise<BotResult>;
/**
* Detect sensitive info in a value.
*
* @param context
* Context.
* @param value
* Value.
* @param entities
* Strategy to use for detecting sensitive info;
* either by denying everything and allowing certain tags or by allowing
* everything and denying certain tags.
* @param contextWindowSize
* Number of tokens to pass to `detect`.
* @param detect
* Function to detect sensitive info (optional).
* @returns
* Promise for a result.
*/
declare function detectSensitiveInfo(context: AnalyzeContext, value: string, entities: SensitiveInfoEntities, contextWindowSize: number, detect?: DetectSensitiveInfoFunction): Promise<SensitiveInfoResult>;
/**
* Check if a filter matches a request.
*
* @param context
* Arcjet context.
* @param request
* Request.
* @param localFields
* Fields to use as `local` in the expressions, as serialized JSON.
* @param expressions
* Filter expressions.
* @returns
* Promise to whether the filter matches the request.
*/
declare function matchFilters(context: AnalyzeContext, request: AnalyzeRequest, localFields: string, expressions: ReadonlyArray<string>, allowIfMatch: boolean): Promise<FilterResult>;
//#endregion
export { AnalyzeRequest, type BotConfig, type DetectedSensitiveInfoEntity, type EmailValidationConfig, type FilterResult, type SensitiveInfoEntity, detectBot, detectSensitiveInfo, generateFingerprint, isValidEmail, matchFilters };
import { initializeWasm } from "@arcjet/analyze-wasm";
//#region src/index.ts
const FREE_EMAIL_PROVIDERS = [
"gmail.com",
"yahoo.com",
"hotmail.com",
"aol.com",
"hotmail.co.uk"
];
function noOpSensitiveInfoDetect() {
return [];
}
function noOpBotsDetect() {
return [];
}
function createCoreImports(detect) {
if (typeof detect !== "function") detect = noOpSensitiveInfoDetect;
return {
"arcjet:js-req/bot-identifier": { detect: noOpBotsDetect },
"arcjet:js-req/email-validator-overrides": {
isFreeEmail(domain) {
if (FREE_EMAIL_PROVIDERS.includes(domain)) return "yes";
return "unknown";
},
isDisposableEmail() {
return "unknown";
},
hasMxRecords() {
return "unknown";
},
hasGravatar() {
return "unknown";
}
},
"arcjet:js-req/filter-overrides": { ipLookup() {} },
"arcjet:js-req/sensitive-information-identifier": { detect },
"arcjet:js-req/verify-bot": { verify() {
return "unverifiable";
} }
};
}
/**
* Generate a fingerprint.
*
* Fingerprints can be used to identify the client across multiple requests.
*
* This considers different things on the `request` based on the passed
* `context.characteristics`.
*
* See [*Fingerprints* on
* `docs.arcjet.com`](https://docs.arcjet.com/fingerprints/) for more info.
*
* @param context
* Context.
* @param request
* Request.
* @returns
* Promise for a SHA-256 fingerprint.
*/
async function generateFingerprint(context, request) {
const { log } = context;
const analyze = await initializeWasm(createCoreImports());
if (typeof analyze !== "undefined") return analyze.generateFingerprint(JSON.stringify(request), context.characteristics);
log.debug("WebAssembly is not supported in this runtime");
return "";
}
/**
* Check whether an email is valid.
*
* @param context
* Context.
* @param value
* Value.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
async function isValidEmail(context, value, options) {
const { log } = context;
const analyze = await initializeWasm(createCoreImports());
if (typeof analyze !== "undefined") return analyze.isValidEmail(value, options);
log.debug("WebAssembly is not supported in this runtime");
return {
blocked: [],
validity: "valid"
};
}
/**
* Detect whether a request is by a bot.
*
* @param context
* Context.
* @param request
* Request.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
async function detectBot(context, request, options) {
const { log } = context;
const analyze = await initializeWasm(createCoreImports());
if (typeof analyze !== "undefined") return analyze.detectBot(JSON.stringify(request), options);
log.debug("WebAssembly is not supported in this runtime");
return {
allowed: [],
denied: [],
spoofed: false,
verified: false
};
}
/**
* Detect sensitive info in a value.
*
* @param context
* Context.
* @param value
* Value.
* @param entities
* Strategy to use for detecting sensitive info;
* either by denying everything and allowing certain tags or by allowing
* everything and denying certain tags.
* @param contextWindowSize
* Number of tokens to pass to `detect`.
* @param detect
* Function to detect sensitive info (optional).
* @returns
* Promise for a result.
*/
async function detectSensitiveInfo(context, value, entities, contextWindowSize, detect) {
const { log } = context;
const analyze = await initializeWasm(createCoreImports(detect));
if (typeof analyze !== "undefined") {
const skipCustomDetect = typeof detect !== "function";
return analyze.detectSensitiveInfo(value, {
entities,
contextWindowSize,
skipCustomDetect
});
}
log.debug("WebAssembly is not supported in this runtime");
throw new Error("SENSITIVE_INFO rule failed to run because Wasm is not supported in this environment.");
}
/**
* Check if a filter matches a request.
*
* @param context
* Arcjet context.
* @param request
* Request.
* @param localFields
* Fields to use as `local` in the expressions, as serialized JSON.
* @param expressions
* Filter expressions.
* @returns
* Promise to whether the filter matches the request.
*/
async function matchFilters(context, request, localFields, expressions, allowIfMatch) {
const analyze = await initializeWasm(createCoreImports());
if (typeof analyze !== "undefined") return analyze.matchFilters(JSON.stringify(request), localFields, expressions, allowIfMatch);
context.log.debug("WebAssembly is not supported in this runtime");
throw new Error("FILTER rule failed to run because Wasm is not supported in this environment.");
}
//#endregion
export { detectBot, detectSensitiveInfo, generateFingerprint, isValidEmail, matchFilters };
+32
-30
{
"name": "@arcjet/analyze",
"version": "1.6.1",
"version": "1.7.0-rc.0",
"description": "Arcjet local analysis engine",

@@ -13,9 +13,3 @@ "keywords": [

],
"license": "Apache-2.0",
"homepage": "https://arcjet.com",
"repository": {
"type": "git",
"url": "git+https://github.com/arcjet/arcjet-js.git",
"directory": "analyze"
},
"bugs": {

@@ -25,2 +19,3 @@ "url": "https://github.com/arcjet/arcjet-js/issues",

},
"license": "Apache-2.0",
"author": {

@@ -31,36 +26,43 @@ "name": "Arcjet",

},
"engines": {
"node": ">=22.21.0 <23 || >=24.5.0"
"repository": {
"type": "git",
"url": "git+https://github.com/arcjet/arcjet-js.git",
"directory": "analyze"
},
"type": "module",
"main": "./index.js",
"types": "./index.d.ts",
"files": [
"index.d.ts",
"index.js"
"dist"
],
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public",
"tag": "latest"
},
"scripts": {
"build": "rollup --config rollup.config.js",
"lint": "eslint .",
"test-api": "node --test -- test/*.test.js",
"test-coverage": "node --experimental-test-coverage --test -- test/*.test.js",
"test": "npm run build && npm run lint && npm run test-coverage"
"build": "tsdown",
"typecheck": "tsgo --noEmit",
"test-api": "node --test -- test/*.test.ts",
"test-coverage": "node --experimental-test-coverage --test -- test/*.test.ts",
"test": "npm run build && npm run test-coverage"
},
"dependencies": {
"@arcjet/analyze-wasm": "1.6.1",
"@arcjet/protocol": "1.6.1"
"@arcjet/analyze-wasm": "1.7.0-rc.0",
"@arcjet/protocol": "1.7.0-rc.0"
},
"devDependencies": {
"@arcjet/eslint-config": "1.6.1",
"@arcjet/rollup-config": "1.6.1",
"@bytecodealliance/jco": "1.5.0",
"@rollup/wasm-node": "4.62.2",
"@types/node": "22.19.21",
"eslint": "9.39.4",
"typescript": "5.9.3"
"tsdown": "0.22.3",
"typescript": "6.0.3"
},
"publishConfig": {
"access": "public",
"tag": "latest"
"engines": {
"node": ">=22.21.0 <23 || >=24.5.0"
}
}
import type { BotConfig, BotResult, DetectedSensitiveInfoEntity, DetectSensitiveInfoFunction, EmailValidationConfig, EmailValidationResult, FilterResult, SensitiveInfoEntities, SensitiveInfoEntity, SensitiveInfoResult } from "@arcjet/analyze-wasm";
import type { ArcjetLogger } from "@arcjet/protocol";
interface AnalyzeContext {
log: ArcjetLogger;
characteristics: string[];
}
/**
* Request passed as a JSON string into WebAssembly.
*
* This is like `ArcjetRequestDetails` from `@arcjet/protocol`,
* but fields are often optional across the boundary.
*/
export interface AnalyzeRequest {
/**
* IP address (IPv4 or IPv6).
*/
ip?: string | undefined;
/**
* HTTP method (such as `GET`).
*/
method?: string | undefined;
/**
* Protocol (such as `"http:"`).
*/
protocol?: string | undefined;
/**
* Hostname (such as `"example.com"`).
*/
host?: string | undefined;
/**
* Path (such as `"/path/to/resource"`).
*/
path?: string | undefined;
/**
* Headers of the request.
*/
headers?: Record<string, string> | undefined;
/**
* Cookies of the request (such as `"cookie1=value1; cookie2=value2"`).
*/
cookies?: string | undefined;
/**
* Query string of the request (such as `"?q=alpha"`).
*/
query?: string | undefined;
/**
* Extra info.
*/
extra?: Record<string, string> | undefined;
}
export { type EmailValidationConfig, type BotConfig, type FilterResult, type SensitiveInfoEntity, type DetectedSensitiveInfoEntity, };
/**
* Generate a fingerprint.
*
* Fingerprints can be used to identify the client across multiple requests.
*
* This considers different things on the `request` based on the passed
* `context.characteristics`.
*
* See [*Fingerprints* on
* `docs.arcjet.com`](https://docs.arcjet.com/fingerprints/) for more info.
*
* @param context
* Context.
* @param request
* Request.
* @returns
* Promise for a SHA-256 fingerprint.
*/
export declare function generateFingerprint(context: AnalyzeContext, request: AnalyzeRequest): Promise<string>;
/**
* Check whether an email is valid.
*
* @param context
* Context.
* @param value
* Value.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
export declare function isValidEmail(context: AnalyzeContext, value: string, options: EmailValidationConfig): Promise<EmailValidationResult>;
/**
* Detect whether a request is by a bot.
*
* @param context
* Context.
* @param request
* Request.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
export declare function detectBot(context: AnalyzeContext, request: AnalyzeRequest, options: BotConfig): Promise<BotResult>;
/**
* Detect sensitive info in a value.
*
* @param context
* Context.
* @param value
* Value.
* @param entities
* Strategy to use for detecting sensitive info;
* either by denying everything and allowing certain tags or by allowing
* everything and denying certain tags.
* @param contextWindowSize
* Number of tokens to pass to `detect`.
* @param detect
* Function to detect sensitive info (optional).
* @returns
* Promise for a result.
*/
export declare function detectSensitiveInfo(context: AnalyzeContext, value: string, entities: SensitiveInfoEntities, contextWindowSize: number, detect?: DetectSensitiveInfoFunction): Promise<SensitiveInfoResult>;
/**
* Check if a filter matches a request.
*
* @param context
* Arcjet context.
* @param request
* Request.
* @param localFields
* Fields to use as `local` in the expressions, as serialized JSON.
* @param expressions
* Filter expressions.
* @returns
* Promise to whether the filter matches the request.
*/
export declare function matchFilters(context: AnalyzeContext, request: AnalyzeRequest, localFields: string, expressions: ReadonlyArray<string>, allowIfMatch: boolean): Promise<FilterResult>;
import { initializeWasm } from '@arcjet/analyze-wasm';
const FREE_EMAIL_PROVIDERS = [
"gmail.com",
"yahoo.com",
"hotmail.com",
"aol.com",
"hotmail.co.uk",
];
function noOpSensitiveInfoDetect() {
return [];
}
function noOpBotsDetect() {
return [];
}
function createCoreImports(detect) {
if (typeof detect !== "function") {
detect = noOpSensitiveInfoDetect;
}
return {
"arcjet:js-req/bot-identifier": {
detect: noOpBotsDetect,
},
"arcjet:js-req/email-validator-overrides": {
isFreeEmail(domain) {
if (FREE_EMAIL_PROVIDERS.includes(domain)) {
return "yes";
}
return "unknown";
},
isDisposableEmail() {
return "unknown";
},
hasMxRecords() {
return "unknown";
},
hasGravatar() {
return "unknown";
},
},
"arcjet:js-req/filter-overrides": {
ipLookup() {
return undefined;
},
},
// TODO(@wooorm-arcjet): figure out a test case for this with the default `detect`.
"arcjet:js-req/sensitive-information-identifier": {
detect,
},
// TODO(@wooorm-arcjet): figure out a test case for this that calls `verify`.
"arcjet:js-req/verify-bot": {
verify() {
return "unverifiable";
},
},
};
}
/**
* Generate a fingerprint.
*
* Fingerprints can be used to identify the client across multiple requests.
*
* This considers different things on the `request` based on the passed
* `context.characteristics`.
*
* See [*Fingerprints* on
* `docs.arcjet.com`](https://docs.arcjet.com/fingerprints/) for more info.
*
* @param context
* Context.
* @param request
* Request.
* @returns
* Promise for a SHA-256 fingerprint.
*/
async function generateFingerprint(context, request) {
const { log } = context;
const coreImports = createCoreImports();
const analyze = await initializeWasm(coreImports);
if (typeof analyze !== "undefined") {
return analyze.generateFingerprint(JSON.stringify(request), context.characteristics);
// Ignore the `else` branch as we test in places that have WebAssembly.
/* node:coverage ignore next 4 */
}
log.debug("WebAssembly is not supported in this runtime");
return "";
}
/**
* Check whether an email is valid.
*
* @param context
* Context.
* @param value
* Value.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
async function isValidEmail(context, value, options) {
const { log } = context;
const coreImports = createCoreImports();
const analyze = await initializeWasm(coreImports);
if (typeof analyze !== "undefined") {
return analyze.isValidEmail(value, options);
// Ignore the `else` branch as we test in places that have WebAssembly.
/* node:coverage ignore next 4 */
}
log.debug("WebAssembly is not supported in this runtime");
return { blocked: [], validity: "valid" };
}
/**
* Detect whether a request is by a bot.
*
* @param context
* Context.
* @param request
* Request.
* @param options
* Configuration.
* @returns
* Promise for a result.
*/
async function detectBot(context, request, options) {
const { log } = context;
const coreImports = createCoreImports();
const analyze = await initializeWasm(coreImports);
if (typeof analyze !== "undefined") {
return analyze.detectBot(JSON.stringify(request), options);
// Ignore the `else` branch as we test in places that have WebAssembly.
/* node:coverage ignore next 4 */
}
log.debug("WebAssembly is not supported in this runtime");
return { allowed: [], denied: [], spoofed: false, verified: false };
}
/**
* Detect sensitive info in a value.
*
* @param context
* Context.
* @param value
* Value.
* @param entities
* Strategy to use for detecting sensitive info;
* either by denying everything and allowing certain tags or by allowing
* everything and denying certain tags.
* @param contextWindowSize
* Number of tokens to pass to `detect`.
* @param detect
* Function to detect sensitive info (optional).
* @returns
* Promise for a result.
*/
async function detectSensitiveInfo(context, value, entities, contextWindowSize, detect) {
const { log } = context;
const coreImports = createCoreImports(detect);
const analyze = await initializeWasm(coreImports);
if (typeof analyze !== "undefined") {
const skipCustomDetect = typeof detect !== "function";
return analyze.detectSensitiveInfo(value, {
entities,
contextWindowSize,
skipCustomDetect,
});
// Ignore the `else` branch as we test in places that have WebAssembly.
/* node:coverage ignore next 4 */
}
log.debug("WebAssembly is not supported in this runtime");
throw new Error("SENSITIVE_INFO rule failed to run because Wasm is not supported in this environment.");
}
/**
* Check if a filter matches a request.
*
* @param context
* Arcjet context.
* @param request
* Request.
* @param localFields
* Fields to use as `local` in the expressions, as serialized JSON.
* @param expressions
* Filter expressions.
* @returns
* Promise to whether the filter matches the request.
*/
async function matchFilters(context, request, localFields, expressions, allowIfMatch) {
const coreImports = createCoreImports();
const analyze = await initializeWasm(coreImports);
if (typeof analyze !== "undefined") {
return analyze.matchFilters(JSON.stringify(request), localFields,
// @ts-expect-error: WebAssembly does not support readonly values.
expressions, allowIfMatch);
// Ignore the `else` branch as we test in places that have WebAssembly.
/* node:coverage ignore next 4 */
}
context.log.debug("WebAssembly is not supported in this runtime");
throw new Error("FILTER rule failed to run because Wasm is not supported in this environment.");
}
export { detectBot, detectSensitiveInfo, generateFingerprint, isValidEmail, matchFilters };