@slopit/core
v0.1.0
Published
Core types, schemas, and validation for slopit behavioral analytics
Downloads
10
Maintainers
Readme
@slopit/core
Core type definitions, schemas, and utilities for the slopit behavioral capture toolkit.
Installation
pnpm add @slopit/coreQuick Start
import {
generateSessionId,
hashText,
validateSession,
captureEnvironment,
} from "@slopit/core";
// generate unique identifiers
const sessionId = generateSessionId();
// hash sensitive text
const hash = await hashText("user input text");
// capture browser environment
const env = captureEnvironment();
// validate session data
const result = validateSession(sessionData);
if (!result.success) {
console.error("Validation errors:", result.errors);
}Type Definitions
Session Types
SlopitSession
The top-level container for all data from a research session.
interface SlopitSession {
schemaVersion: string;
sessionId: string;
participantId?: string;
studyId?: string;
platform: PlatformInfo;
environment: EnvironmentInfo;
timing: SessionTiming;
trials: SlopitTrial[];
globalEvents: GlobalEvents;
}SlopitTrial
Data for a single trial within a session.
interface SlopitTrial {
trialId: string;
trialIndex: number;
trialType: string;
startTime: number;
endTime: number;
rt: number;
stimulus?: StimulusInfo;
response?: ResponseInfo;
behavioral?: BehavioralData;
captureFlags?: CaptureFlag[];
platformData?: Record<string, unknown>;
}PlatformInfo
Information about the experiment platform.
interface PlatformInfo {
name: string; // e.g., "jspsych"
version: string; // platform version
adapterVersion: string; // slopit adapter version
}EnvironmentInfo
Browser and system environment data.
interface EnvironmentInfo {
userAgent: string;
language: string;
platform: string;
screenWidth: number;
screenHeight: number;
windowWidth: number;
windowHeight: number;
devicePixelRatio: number;
timezone: string;
timezoneOffset: number;
}SessionTiming
Timing information for the session.
interface SessionTiming {
startTime: number; // Unix timestamp in milliseconds
endTime: number; // Unix timestamp in milliseconds
duration: number; // Total duration in milliseconds
}Behavioral Event Types
KeystrokeEvent
A single keystroke event.
| Field | Type | Description | |-------|------|-------------| | time | number | Time since trial start in milliseconds | | key | string | Key value from KeyboardEvent.key (e.g., "a", "Enter", "Backspace") | | code | string | Physical key code from KeyboardEvent.code (e.g., "KeyA", "Enter") | | event | "keydown" | "keyup" | Event type | | textLength | number? | Current text length at this moment | | modifiers | ModifierState? | Modifier key states |
ModifierState
Modifier key states at time of keystroke.
interface ModifierState {
shift: boolean;
ctrl: boolean;
alt: boolean;
meta: boolean;
}FocusEvent
A focus or visibility change event.
| Field | Type | Description | |-------|------|-------------| | time | number | Time since trial start in milliseconds | | event | "focus" | "blur" | "visibilitychange" | Event type | | visibility | "visible" | "hidden"? | For visibilitychange events, the new state | | blurDuration | number? | For blur events, duration until refocus (filled retrospectively) |
PasteEvent
A paste event.
| Field | Type | Description | |-------|------|-------------| | time | number | Time since trial start in milliseconds | | textLength | number | Length of pasted text in characters | | textPreview | string? | First N characters of pasted text (default N=100) | | textHash | string? | SHA-256 hash of full pasted text | | precedingKeystrokes | number | Number of keystrokes in preceding 2 seconds | | blocked | boolean | Whether paste was blocked by configuration |
MouseEvent
A mouse event.
| Field | Type | Description | |-------|------|-------------| | time | number | Time since trial start in milliseconds | | event | "mousemove" | "mousedown" | "mouseup" | "click" | Event type | | x | number | X coordinate relative to viewport | | y | number | Y coordinate relative to viewport | | velocity | number? | Velocity in pixels per millisecond (for mousemove) | | distance | number? | Distance traveled since last event in pixels | | deltaTime | number? | Time since last mouse event in milliseconds | | isDragging | boolean? | Whether this event is part of a drag operation |
ScrollEvent
A scroll event.
| Field | Type | Description | |-------|------|-------------| | time | number | Time since trial start in milliseconds | | direction | "up" | "down" | Direction of scroll | | deltaY | number | Scroll delta in pixels | | scrollTop | number | Current scroll position from top | | scrollHeight | number | Scrollable element height | | clientHeight | number | Viewport height | | velocity | number? | Velocity in pixels per millisecond |
ClipboardCopyEvent
A clipboard copy or cut event.
| Field | Type | Description | |-------|------|-------------| | time | number | Time since trial start in milliseconds | | event | "copy" | "cut" | Event type | | textLength | number | Length of selected text | | textPreview | string? | First N characters of copied text | | textHash | string? | SHA-256 hash of copied text | | selectionStart | number? | Selection start index in input element | | selectionEnd | number? | Selection end index in input element |
InputDurationEvent
An input duration event tracking focus sessions.
| Field | Type | Description | |-------|------|-------------| | focusTime | number | Time since trial start when focus was gained | | blurTime | number | Time since trial start when focus was lost | | duration | number | Duration focused in milliseconds | | elementId | string? | Element identifier (id or name attribute) | | keystrokesDuringFocus | number? | Number of keystrokes during focus | | pastesDuringFocus | number? | Number of paste events during focus |
Behavioral Metrics Types
BehavioralData
Container for all behavioral capture data.
interface BehavioralData {
keystrokes?: KeystrokeEvent[];
focus?: FocusEvent[];
paste?: PasteEvent[];
mouse?: MouseEvent[];
scroll?: ScrollEvent[];
clipboard?: ClipboardCopyEvent[];
inputDuration?: InputDurationEvent[];
metrics?: BehavioralMetrics;
}BehavioralMetrics
Computed metrics from behavioral data.
interface BehavioralMetrics {
keystroke?: KeystrokeMetrics;
focus?: FocusMetrics;
timing?: TimingMetrics;
mouse?: MouseMetrics;
scroll?: ScrollMetrics;
inputDuration?: InputDurationMetrics;
}KeystrokeMetrics
Metrics computed from keystroke data.
| Field | Type | Description | |-------|------|-------------| | totalKeystrokes | number | Total number of keystrokes | | printableKeystrokes | number | Number of printable character keystrokes | | deletions | number | Number of deletion keystrokes (Backspace, Delete) | | meanIKI | number | Mean inter-keystroke interval in milliseconds | | stdIKI | number | Standard deviation of IKI | | medianIKI | number | Median IKI | | pauseCount | number | Number of pauses (IKI > threshold) | | productProcessRatio | number | Ratio of final characters to total keystrokes |
FocusMetrics
Metrics computed from focus data.
| Field | Type | Description | |-------|------|-------------| | blurCount | number | Number of blur events | | totalBlurDuration | number | Total time in milliseconds with window blurred | | hiddenCount | number | Number of visibility hidden events | | totalHiddenDuration | number | Total time in milliseconds with document hidden |
TimingMetrics
Timing metrics.
| Field | Type | Description | |-------|------|-------------| | firstKeystrokeLatency | number? | Time from trial start to first keystroke | | totalResponseTime | number | Time from trial start to response submission | | charactersPerMinute | number? | Characters per minute (excluding deletions) |
MouseMetrics
Metrics computed from mouse data.
| Field | Type | Description | |-------|------|-------------| | totalEvents | number | Total number of mouse events | | clickCount | number | Number of click events | | meanVelocity | number | Mean mouse velocity in pixels per millisecond | | totalDistance | number | Total distance traveled by cursor in pixels | | totalIdleTime | number | Total idle time with no mouse movement | | idlePeriodCount | number | Number of idle periods exceeding threshold |
ScrollMetrics
Metrics computed from scroll data.
| Field | Type | Description | |-------|------|-------------| | totalScrollEvents | number | Total number of scroll events | | totalScrollDistance | number | Total scroll distance in pixels | | directionChanges | number | Number of scroll direction changes | | meanScrollVelocity | number | Mean scroll velocity | | upDownRatio | number | Time spent scrolling up vs down ratio |
InputDurationMetrics
Metrics computed from input duration data.
| Field | Type | Description | |-------|------|-------------| | totalFocusDuration | number | Total focus duration across all inputs | | meanFocusDuration | number | Mean focus duration per input session | | focusSessionCount | number | Number of focus sessions | | maxFocusDuration | number | Longest single focus session |
Flag Types
CaptureFlag
Flag generated during data capture.
interface CaptureFlag {
type: string; // Flag type identifier
severity: Severity; // "info" | "low" | "medium" | "high"
message: string; // Human-readable description
timestamp: number; // Timestamp when flag was generated
details?: Record<string, unknown>; // Additional details
}AnalysisFlag
Flag generated during server-side analysis.
interface AnalysisFlag {
type: string; // Flag type identifier
analyzer: string; // Analyzer that generated this flag
severity: Severity; // "info" | "low" | "medium" | "high"
message: string; // Human-readable description
confidence?: number; // Confidence score (0.0 to 1.0)
evidence?: Record<string, unknown>;// Evidence supporting this flag
trialIds?: string[]; // Related trial IDs if trial-specific
}Severity
Severity level for flags.
type Severity = "info" | "low" | "medium" | "high";Validation
validateSession
Validates a session object against the schema.
import { validateSession } from "@slopit/core";
const result = validateSession(sessionData);
if (result.success) {
console.log("Session is valid");
} else {
console.error("Validation errors:", result.errors);
}isValidSession
Type guard for checking session validity.
import { isValidSession } from "@slopit/core";
if (isValidSession(data)) {
// data is typed as SlopitSession
console.log(data.sessionId);
}Zod Schemas
The package exports Zod schemas for all types.
import {
SlopitSessionSchema,
SlopitTrialSchema,
BehavioralDataSchema,
KeystrokeEventSchema,
FocusEventSchema,
PasteEventSchema,
CaptureFlagSchema,
AnalysisFlagSchema,
} from "@slopit/core";
// parse and validate data
const keystroke = KeystrokeEventSchema.parse(rawData);
// safe parse with error handling
const result = SlopitTrialSchema.safeParse(trialData);
if (!result.success) {
console.error(result.error.issues);
}Utility Functions
ID Generation
generateSessionId
Generates a unique session identifier.
import { generateSessionId } from "@slopit/core";
const id = generateSessionId();
// Returns: "session_1706123456789_a1b2c3d4"generateTrialId
Generates a unique trial identifier.
import { generateTrialId } from "@slopit/core";
const id = generateTrialId();
// Returns: "trial_1706123456789_e5f6g7h8"Hashing
hashText
Computes SHA-256 hash of text using Web Crypto API.
import { hashText } from "@slopit/core";
const hash = await hashText("Hello, world!");
// Returns: "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"simpleHash
Synchronous simple hash for non-cryptographic purposes.
import { simpleHash } from "@slopit/core";
const hash = simpleHash("Hello, world!");
// Returns: "0a1b2c3d" (8-character hex string)Timing
now
Returns current Unix timestamp in milliseconds.
import { now } from "@slopit/core";
const timestamp = now();
// Returns: 1706123456789highResTime
Returns high-resolution timestamp for performance measurement.
import { highResTime } from "@slopit/core";
const start = highResTime();
// ... do work
const elapsed = highResTime() - start;duration
Calculates duration between two timestamps.
import { duration } from "@slopit/core";
const elapsed = duration(startTime); // from startTime to now
const elapsed = duration(startTime, endTime); // from startTime to endTimeformatDuration
Formats a duration in human-readable format.
import { formatDuration } from "@slopit/core";
formatDuration(65000); // "1m 5s"
formatDuration(3661000); // "1h 1m 1s"
formatDuration(500); // "500ms"toTimestamp / fromTimestamp
Converts between Date objects and Unix timestamps.
import { toTimestamp, fromTimestamp } from "@slopit/core";
const timestamp = toTimestamp(new Date());
const date = fromTimestamp(1706123456789);Environment
captureEnvironment
Captures browser and system environment information.
import { captureEnvironment } from "@slopit/core";
const env = captureEnvironment();
/*
{
userAgent: "Mozilla/5.0 ...",
language: "en-US",
platform: "MacIntel",
screenWidth: 2560,
screenHeight: 1440,
windowWidth: 1920,
windowHeight: 1080,
devicePixelRatio: 2,
timezone: "America/New_York",
timezoneOffset: -300
}
*/Constants
import {
SCHEMA_VERSION,
DEFAULT_CONFIG,
SEVERITY_LEVELS,
KNOWN_PLATFORMS,
} from "@slopit/core";
console.log(SCHEMA_VERSION); // "1.0.0"
console.log(SEVERITY_LEVELS); // ["info", "low", "medium", "high"]
console.log(KNOWN_PLATFORMS); // ["jspsych", "pavlovia", "gorilla", ...]Package Exports
The package provides multiple entry points:
// main entry point with all exports
import { ... } from "@slopit/core";
// schemas only
import { ... } from "@slopit/core/schemas";
// validation only
import { ... } from "@slopit/core/validation";License
MIT
