diff --git a/src/constants.ts b/src/constants.ts index e69de29..0bf192d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -0,0 +1,11 @@ +/** + * Matches 64-character lowercase hexadecimal strings. + * Used for validating event IDs and cryptographic keys. + */ +export const HEX_64_PATTERN = /^[a-f0-9]{64}$/; + +/** + * Matches 128-character lowercase hexadecimal strings. + * Used for validating signatures. + */ +export const HEX_128_PATTERN = /^[a-f0-9]{128}$/; diff --git a/src/errors.ts b/src/errors.ts index e69de29..6818dfb 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -0,0 +1,79 @@ +/** + * Public key is not 64 lowercase hex characters. + */ +export class MalformedPubKeyError extends Error { + constructor() { + super("public key must be 64 lowercase hex characters"); + this.name = "MalformedPubKeyError"; + } +} + +/** + * Private key is not 64 lowercase hex characters. + */ +export class MalformedPrivKeyError extends Error { + constructor() { + super("private key must be 64 lowercase hex characters"); + this.name = "MalformedPrivKeyError"; + } +} + +/** + * Event ID is not 64 hex characters. + */ +export class MalformedIDError extends Error { + constructor() { + super("event id must be 64 hex characters"); + this.name = "MalformedIDError"; + } +} + +/** + * Event signature is not 128 hex characters. + */ +export class MalformedSigError extends Error { + constructor() { + super("event signature must be 128 hex characters"); + this.name = "MalformedSigError"; + } +} + +/** + * Event tag contains fewer than two elements. + */ +export class MalformedTagError extends Error { + constructor() { + super("tags must contain at least two elements"); + this.name = "MalformedTagError"; + } +} + +/** + * Event ID could not be computed during validation. + */ +export class FailedIDCompError extends Error { + constructor() { + super("failed to compute event id"); + this.name = "FailedIDCompError"; + } +} + +/** + * Event ID field is empty. + */ +export class NoEventIDError extends Error { + constructor() { + super("event id is empty"); + this.name = "NoEventIDError"; + } +} + +/** + * Event signature failed cryptographic validation. + */ +export class InvalidSigError extends Error { + constructor() { + super("event signature is invalid"); + this.name = "InvalidSigError"; + } +} diff --git a/src/types.ts b/src/types.ts index e69de29..95f50ed 100644 --- a/src/types.ts +++ b/src/types.ts @@ -0,0 +1,51 @@ +/** + * Tag represents a single tag within an event as an array of strings. + * The first element identifies the tag name, the second contains the value, + * and subsequent elements are optional. + */ +export type Tag = string[]; + +/** + * Event represents a Nostr protocol event with its seven required fields. + * All fields must be present for a valid event. + */ +export interface Event { + id: string; + pubkey: string; + created_at: number; + kind: number; + tags: Tag[]; + content: string; + sig: string; +} + +/** + * TagFilters maps tag names to arrays of values for tag-based filtering. + * Keys correspond to tag names without the "#" prefix. + */ +export interface TagFilters { + [tagName: string]: string[]; +} + +/** + * FilterExtensions holds arbitrary additional filter fields as raw JSON values. + * Allows custom filter extensions without modifying the core Filter type. + */ +export interface FilterExtensions { + [key: string]: unknown; +} + +/** + * Filter defines subscription criteria for events. + * All conditions within a filter are applied with AND logic. + */ +export interface Filter { + ids?: string[]; + authors?: string[]; + kinds?: number[]; + since?: number; + until?: number; + limit?: number; + tags?: TagFilters; + extensions?: FilterExtensions; +}