{"version":3,"sources":["../src/validation.ts","../src/operation-context.ts"],"names":["AsyncLocalStorage"],"mappings":"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","file":"chunk-D5LMF53P.cjs","sourcesContent":["/**\n * Input validation for events events and attributes\n *\n * Prevents:\n * - Invalid event names\n * - Oversized payloads\n * - Circular references\n * - Sensitive data leaks\n */\n\nimport type { EventAttributes } from './event-subscriber';\n\nexport interface ValidationConfig {\n  /** Max event name length (default: 100) */\n  maxEventNameLength: number;\n  /** Max attribute key length (default: 100) */\n  maxAttributeKeyLength: number;\n  /** Max attribute value length for strings (default: 1000) */\n  maxAttributeValueLength: number;\n  /** Max total attributes per event (default: 50) */\n  maxAttributeCount: number;\n  /** Max nesting depth for objects (default: 3) */\n  maxNestingDepth: number;\n  /** Sensitive field patterns to redact */\n  sensitivePatterns: RegExp[];\n}\n\nconst DEFAULT_CONFIG: ValidationConfig = {\n  maxEventNameLength: 100,\n  maxAttributeKeyLength: 100,\n  maxAttributeValueLength: 1000,\n  maxAttributeCount: 50,\n  maxNestingDepth: 3,\n  sensitivePatterns: [\n    /password/i,\n    /secret/i,\n    /token/i,\n    /api[_-]?key/i,\n    /access[_-]?key/i,\n    /private[_-]?key/i,\n    /auth/i,\n    /credential/i,\n    /ssn/i,\n    /credit[_-]?card/i,\n  ],\n};\n\nexport class ValidationError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'ValidationError';\n  }\n}\n\n/**\n * Validate and sanitize event name\n * Throws ValidationError if invalid\n */\nexport function validateEventName(\n  eventName: string,\n  config: ValidationConfig = DEFAULT_CONFIG,\n): string {\n  // Check type\n  if (typeof eventName !== 'string') {\n    throw new ValidationError(\n      `Event name must be a string, got ${typeof eventName}`,\n    );\n  }\n\n  // Check non-empty\n  const trimmed = eventName.trim();\n  if (trimmed.length === 0) {\n    throw new ValidationError('Event name cannot be empty');\n  }\n\n  // Check length\n  if (trimmed.length > config.maxEventNameLength) {\n    throw new ValidationError(\n      `Event name too long (${trimmed.length} chars). ` +\n        `Max: ${config.maxEventNameLength}`,\n    );\n  }\n\n  // Check valid characters (alphanumeric, dots, underscores, hyphens)\n  if (!/^[a-zA-Z0-9._-]+$/.test(trimmed)) {\n    throw new ValidationError(\n      `Event name contains invalid characters: \"${trimmed}\". ` +\n        'Use only letters, numbers, dots, underscores, and hyphens.',\n    );\n  }\n\n  return trimmed;\n}\n\n/**\n * Validate and sanitize attributes\n * Returns sanitized attributes (sensitive data redacted)\n */\nexport function validateAttributes(\n  attributes: EventAttributes | undefined,\n  config: ValidationConfig = DEFAULT_CONFIG,\n): EventAttributes | undefined {\n  if (attributes === undefined || attributes === null) {\n    return undefined;\n  }\n\n  // Check type\n  if (typeof attributes !== 'object' || Array.isArray(attributes)) {\n    throw new ValidationError('Attributes must be an object');\n  }\n\n  // Count attributes\n  const keys = Object.keys(attributes);\n  if (keys.length > config.maxAttributeCount) {\n    throw new ValidationError(\n      `Too many attributes (${keys.length}). ` +\n        `Max: ${config.maxAttributeCount}`,\n    );\n  }\n\n  // Validate and sanitize each attribute\n  const sanitized: EventAttributes = {};\n\n  for (const key of keys) {\n    // Validate key\n    if (key.length > config.maxAttributeKeyLength) {\n      throw new ValidationError(\n        `Attribute key too long: \"${key.slice(0, 20)}...\" ` +\n          `(${key.length} chars). Max: ${config.maxAttributeKeyLength}`,\n      );\n    }\n\n    // Check for sensitive field\n    const isSensitive = config.sensitivePatterns.some((pattern) =>\n      pattern.test(key),\n    );\n\n    if (isSensitive) {\n      // Redact sensitive data\n      sanitized[key] = '[REDACTED]';\n      continue;\n    }\n\n    // Sanitize value\n    const value = attributes[key];\n    sanitized[key] = sanitizeValue(value, config, 1) as\n      | string\n      | number\n      | boolean;\n  }\n\n  return sanitized;\n}\n\n/**\n * Sanitize attribute value (recursive)\n */\nfunction sanitizeValue(\n  value: unknown,\n  config: ValidationConfig,\n  depth: number,\n): unknown {\n  // Check nesting depth\n  if (depth > config.maxNestingDepth) {\n    return '[MAX_DEPTH_EXCEEDED]';\n  }\n\n  // Handle null/undefined\n  if (value === null || value === undefined) {\n    return value;\n  }\n\n  // Handle primitives\n  if (typeof value === 'string') {\n    if (value.length > config.maxAttributeValueLength) {\n      return value.slice(0, config.maxAttributeValueLength) + '...';\n    }\n    return value;\n  }\n\n  if (typeof value === 'number' || typeof value === 'boolean') {\n    return value;\n  }\n\n  // Handle arrays\n  if (Array.isArray(value)) {\n    return value.map((item) => sanitizeValue(item, config, depth + 1));\n  }\n\n  // Handle objects\n  if (typeof value === 'object') {\n    try {\n      // Check for circular references\n      JSON.stringify(value);\n\n      const sanitized: Record<string, unknown> = {};\n      for (const key in value) {\n        if (Object.prototype.hasOwnProperty.call(value, key)) {\n          // Check for sensitive field in nested objects\n          const isSensitive = config.sensitivePatterns.some((pattern) =>\n            pattern.test(key),\n          );\n\n          if (isSensitive) {\n            sanitized[key] = '[REDACTED]';\n          } else {\n            sanitized[key] = sanitizeValue(\n              (value as Record<string, unknown>)[key],\n              config,\n              depth + 1,\n            );\n          }\n        }\n      }\n      return sanitized;\n    } catch {\n      // Circular reference detected\n      return '[CIRCULAR]';\n    }\n  }\n\n  // Unsupported type (function, symbol, etc.)\n  return `[${typeof value}]`;\n}\n\n/**\n * Validate and sanitize an events event\n * Returns { eventName, attributes } with sanitized values\n */\nexport function validateEvent(\n  eventName: string,\n  attributes?: EventAttributes,\n  config?: Partial<ValidationConfig>,\n): { eventName: string; attributes?: EventAttributes } {\n  const fullConfig = { ...DEFAULT_CONFIG, ...config };\n\n  return {\n    eventName: validateEventName(eventName, fullConfig),\n    attributes: validateAttributes(attributes, fullConfig),\n  };\n}\n\n/**\n * Get default validation config (for testing/customization)\n */\nexport function getDefaultValidationConfig(): ValidationConfig {\n  return { ...DEFAULT_CONFIG };\n}\n","/**\n * Operation context tracking using AsyncLocalStorage\n *\n * This module provides a way to track operation names across async boundaries\n * so they can be automatically captured in events events.\n *\n * We cannot read span attributes from OpenTelemetry's API (it's write-only),\n * so we maintain our own async context storage.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Operation context that flows through async operations\n */\nexport interface OperationContext {\n  /**\n   * The name of the current operation\n   * This is set by trace() or span() and can be read by events\n   */\n  name: string;\n}\n\n/**\n * AsyncLocalStorage instance for tracking operation context\n */\nconst operationStorage = new AsyncLocalStorage<OperationContext>();\n\n/**\n * Get the current operation context (if any)\n *\n * @returns The current operation context, or undefined if not in an operation\n *\n * @example\n * ```typescript\n * const ctx = getOperationContext();\n * if (ctx) {\n *   console.log('Current operation:', ctx.name);\n * }\n * ```\n */\nexport function getOperationContext(): OperationContext | undefined {\n  return operationStorage.getStore();\n}\n\n/**\n * Run a function within an operation context\n *\n * This sets the operation name for the duration of the function execution,\n * including all async operations spawned from it.\n *\n * @param name - The operation name to set\n * @param fn - The function to execute within the context\n * @returns The result of the function\n *\n * @example\n * ```typescript\n * const result = await runInOperationContext('user.create', async () => {\n *   // Any events.trackEvent() calls here will automatically capture\n *   // 'operation.name': 'user.create'\n *   await createUser();\n *   return 'success';\n * });\n * ```\n */\nexport function runInOperationContext<T>(name: string, fn: () => T): T {\n  return operationStorage.run({ name }, fn);\n}\n\n/**\n * Update the operation name in the current context\n *\n * This is useful when you want to change the operation name within\n * an already-established context (e.g., when entering a nested span).\n *\n * @param name - The new operation name\n *\n * @example\n * ```typescript\n * runInOperationContext('parent.operation', () => {\n *   // operation.name is 'parent.operation'\n *\n *   updateOperationName('nested.operation');\n *   // operation.name is now 'nested.operation'\n * });\n * ```\n */\nexport function updateOperationName(name: string): void {\n  const store = operationStorage.getStore();\n  if (store) {\n    store.name = name;\n  }\n}\n"]}