14e38889c5d43a63ed7f2ce3175b82e131f927ceda47f40277b538b1987fe962.json raw

   1  {"ast":null,"code":"import { IdentityId, RelayId } from '../value-objects';\n/**\n * Relay entity - represents a Nostr relay configuration for an identity.\n */\nexport class Relay {\n  _id;\n  _identityId;\n  _url;\n  _read;\n  _write;\n  constructor(id, identityId, url, read, write) {\n    this._id = id;\n    this._identityId = identityId;\n    this._url = Relay.normalizeUrl(url);\n    this._read = read;\n    this._write = write;\n  }\n  // ─────────────────────────────────────────────────────────────────────────\n  // Factory Methods\n  // ─────────────────────────────────────────────────────────────────────────\n  /**\n   * Create a new relay configuration.\n   *\n   * @param identityId - The identity this relay belongs to\n   * @param url - The relay WebSocket URL\n   * @param read - Whether to read events from this relay\n   * @param write - Whether to write events to this relay\n   */\n  static create(identityId, url, read = true, write = true) {\n    Relay.validateUrl(url);\n    return new Relay(RelayId.generate(), identityId, url, read, write);\n  }\n  /**\n   * Reconstitute a relay from storage.\n   */\n  static fromSnapshot(snapshot) {\n    return new Relay(RelayId.from(snapshot.id), IdentityId.from(snapshot.identityId), snapshot.url, snapshot.read, snapshot.write);\n  }\n  // ─────────────────────────────────────────────────────────────────────────\n  // Getters\n  // ─────────────────────────────────────────────────────────────────────────\n  get id() {\n    return this._id;\n  }\n  get identityId() {\n    return this._identityId;\n  }\n  get url() {\n    return this._url;\n  }\n  get read() {\n    return this._read;\n  }\n  get write() {\n    return this._write;\n  }\n  // ─────────────────────────────────────────────────────────────────────────\n  // Behavior\n  // ─────────────────────────────────────────────────────────────────────────\n  /**\n   * Update the relay URL.\n   */\n  updateUrl(newUrl) {\n    Relay.validateUrl(newUrl);\n    this._url = Relay.normalizeUrl(newUrl);\n  }\n  /**\n   * Enable reading from this relay.\n   */\n  enableRead() {\n    this._read = true;\n  }\n  /**\n   * Disable reading from this relay.\n   */\n  disableRead() {\n    this._read = false;\n  }\n  /**\n   * Enable writing to this relay.\n   */\n  enableWrite() {\n    this._write = true;\n  }\n  /**\n   * Disable writing to this relay.\n   */\n  disableWrite() {\n    this._write = false;\n  }\n  /**\n   * Set both read and write permissions.\n   */\n  setPermissions(read, write) {\n    this._read = read;\n    this._write = write;\n  }\n  /**\n   * Check if this relay is enabled for either read or write.\n   */\n  isEnabled() {\n    return this._read || this._write;\n  }\n  /**\n   * Check if this relay has the same URL as another (case-insensitive).\n   */\n  hasSameUrl(url) {\n    return this._url.toLowerCase() === Relay.normalizeUrl(url).toLowerCase();\n  }\n  /**\n   * Check if this relay belongs to a specific identity.\n   */\n  belongsTo(identityId) {\n    return this._identityId.equals(identityId);\n  }\n  // ─────────────────────────────────────────────────────────────────────────\n  // Persistence\n  // ─────────────────────────────────────────────────────────────────────────\n  /**\n   * Convert to a snapshot for persistence.\n   */\n  toSnapshot() {\n    return {\n      id: this._id.value,\n      identityId: this._identityId.value,\n      url: this._url,\n      read: this._read,\n      write: this._write\n    };\n  }\n  /**\n   * Create a clone for modification without affecting the original.\n   */\n  clone() {\n    return new Relay(this._id, this._identityId, this._url, this._read, this._write);\n  }\n  // ─────────────────────────────────────────────────────────────────────────\n  // Equality\n  // ─────────────────────────────────────────────────────────────────────────\n  /**\n   * Check equality based on relay ID.\n   */\n  equals(other) {\n    return this._id.equals(other._id);\n  }\n  // ─────────────────────────────────────────────────────────────────────────\n  // Helpers\n  // ─────────────────────────────────────────────────────────────────────────\n  static normalizeUrl(url) {\n    let normalized = url.trim();\n    // Remove trailing slash\n    if (normalized.endsWith('/')) {\n      normalized = normalized.slice(0, -1);\n    }\n    return normalized;\n  }\n  static validateUrl(url) {\n    const normalized = Relay.normalizeUrl(url);\n    if (!normalized) {\n      throw new InvalidRelayUrlError('Relay URL cannot be empty');\n    }\n    // Must start with wss:// or ws://\n    if (!normalized.startsWith('wss://') && !normalized.startsWith('ws://')) {\n      throw new InvalidRelayUrlError('Relay URL must start with wss:// or ws://');\n    }\n    // Try to parse as URL\n    try {\n      new URL(normalized);\n    } catch {\n      throw new InvalidRelayUrlError(`Invalid relay URL: ${url}`);\n    }\n  }\n}\n/**\n * Error thrown when a relay URL is invalid.\n */\nexport class InvalidRelayUrlError extends Error {\n  constructor(message) {\n    super(message);\n    this.name = 'InvalidRelayUrlError';\n  }\n}\n/**\n * Helper to convert relay list to NIP-65 format.\n */\nexport function toNip65RelayList(relays) {\n  const result = {};\n  for (const relay of relays) {\n    if (relay.isEnabled()) {\n      result[relay.url] = {\n        read: relay.read,\n        write: relay.write\n      };\n    }\n  }\n  return result;\n}","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}