{"version":3,"sources":["../../src/adapters/base-adapter.ts"],"names":["bundleId","vendor"],"mappings":"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","file":"base-adapter.mjs","sourcesContent":["import fs from 'fs';\nimport pathModule from 'path';\n\nimport {OSAdapter} from '../adapter';\nimport {PathInfo, PathMetadata, PathSource} from '../types';\n\n/**\n * Base adapter class that implements common functionality for all OS adapters\n */\nexport abstract class BaseOSAdapter implements OSAdapter {\n  protected pathMap: Map<string, PathInfo> = new Map();\n\n  /**\n   * Add a path to the internal path map\n   *\n   * @param path Path to add\n   * @param source Source information for the path\n   */\n  protected _addPath(path: string, source: PathSource): void {\n    const evaluation = this.evaluatePath(path);\n    const metadata = this._enrichMetadata(evaluation.metadata, path, source);\n\n    if (!this.pathMap.has(path)) {\n      this.pathMap.set(path, {\n        ...evaluation,\n        metadata,\n      });\n    } else {\n      const existing = this.pathMap.get(path)!;\n      if (evaluation.score > existing.score) {\n        existing.score = evaluation.score;\n        existing.metadata = {\n          ...existing.metadata,\n          ...metadata,\n          source,\n          sources: [...(existing.metadata.sources || []), source],\n        };\n      }\n    }\n  }\n\n  /**\n   * Enrich metadata with platform-specific information\n   * Must be implemented by platform-specific adapters\n   *\n   * @param metadata Base metadata\n   * @param path Path to enrich metadata for\n   * @param source Source information\n   * @returns Enriched metadata\n   */\n  protected abstract _enrichMetadata(metadata: PathMetadata, path: string, source: PathSource): PathMetadata;\n\n  /**\n   * Evaluate a path to determine if it exists, is accessible, and assign a score\n   *\n   * @param path Path to evaluate\n   * @returns Path info object with evaluation results\n   */\n  protected evaluatePath(path: string): PathInfo {\n    let exists = false;\n    let isAccessible = false;\n    let score = 0;\n    const metadata: PathMetadata = {};\n\n    try {\n      const stats = fs.statSync(path);\n      exists = true;\n      isAccessible = true;\n      score = 50; // Base score for existing and accessible paths\n      metadata.stats = {\n        mode: stats.mode,\n        uid: stats.uid,\n        gid: stats.gid,\n        size: stats.size,\n        mtime: stats.mtime,\n      };\n    } catch (error: any) {\n      if (error.code === 'ENOENT') {\n        // Path doesn't exist\n        score = 0;\n      } else if (error.code === 'EACCES') {\n        // Path exists but is not accessible\n        exists = true;\n        score = 10;\n      }\n    }\n\n    return {\n      path,\n      exists,\n      isAccessible,\n      score,\n      metadata,\n    };\n  }\n\n  /**\n   * Check if a path is an app storage path\n   *\n   * @param path Path to check\n   * @returns True if the path is an app storage path\n   */\n  protected isAppStoragePath(path: string): boolean {\n    const basename = path.split(pathModule.sep).pop() || '';\n    return basename.includes('~') || basename.startsWith('iCloud');\n  }\n\n  /**\n   * Parse app name from a path\n   *\n   * @param path Path to parse\n   * @returns Object containing app ID, name, bundle ID, and vendor\n   */\n  protected parseAppName(path: string): {appId?: string; appName?: string; bundleId?: string; vendor?: string} {\n    const basename = path.split(pathModule.sep).pop() || '';\n    const parts = basename.split('~');\n\n    if (parts.length < 2) {\n      return {};\n    }\n\n    // Remove any ID prefix (e.g., '4R6749AYRE' in '4R6749AYRE~com~pixelmatorteam~pixelmator')\n    const cleanParts = parts[0].match(/^[A-Z0-9]+$/) ? parts.slice(1) : parts;\n\n    // Handle 'iCloud' prefix\n    const startIndex = cleanParts[0] === 'iCloud' ? 1 : 0;\n\n    // Get the parts for bundleId\n    const bundleParts = cleanParts.slice(startIndex);\n\n    // For bundleId, we need to handle different formats:\n    // 1. com~apple~notes -> com.apple.notes\n    // 2. dk~simonbs~Scriptable -> dk.simonbs.Scriptable\n    // 3. com~company~app~SubApp.Module -> com.company.app.SubApp.Module\n    // 4. com~pixelmatorteam~pixelmator -> com.pixelmatorteam.pixelmator\n    // 5. com~mindnode~MindNode -> com.mindnode.MindNode\n    const appId = parts.join('~');\n    const appName = this._formatAppName(bundleParts[bundleParts.length - 1] || '');\n\n    // If the first part is a known vendor prefix (com, dk, etc.), keep it at the start\n    if (bundleParts[0] === 'com' || bundleParts[0] === 'dk' || bundleParts[0] === 'md') {\n      const bundleId = bundleParts.join('.');\n      const vendor = bundleParts[0] === 'com' ? `${bundleParts[0]}.${bundleParts[1]}` : bundleParts[0];\n      return {appId, appName, bundleId, vendor};\n    }\n\n    // Otherwise, try to find a vendor prefix in the parts\n    const vendorIndex = bundleParts.findIndex(part => part === 'com' || part === 'dk' || part === 'md');\n    if (vendorIndex !== -1) {\n      // Reorder parts to put vendor prefix first\n      const reorderedParts = [\n        bundleParts[vendorIndex],\n        ...bundleParts.slice(0, vendorIndex),\n        ...bundleParts.slice(vendorIndex + 1),\n      ];\n      const bundleId = reorderedParts.join('.');\n      const vendor = reorderedParts[0] === 'com' ? `${reorderedParts[0]}.${reorderedParts[1]}` : reorderedParts[0];\n      return {appId, appName, bundleId, vendor};\n    }\n\n    // If no vendor prefix found, just join the parts\n    const bundleId = bundleParts.join('.');\n    const vendor = bundleParts[0];\n    return {appId, appName, bundleId, vendor};\n  }\n\n  /**\n   * Format app name for display\n   *\n   * @param name Raw app name\n   * @returns Formatted app name\n   */\n  protected _formatAppName(name: string): string {\n    // Handle cases like 'SubApp.Module' -> 'SubApp Module'\n    if (name.includes('.')) {\n      return name\n        .split('.')\n        .map(part => this._formatAppName(part))\n        .join(' ');\n    }\n\n    // Handle cases where we don't want to split camelCase (like 'MindNode')\n    if (/^[A-Z][a-z]+[A-Z][a-z]+$/.test(name)) {\n      return name;\n    }\n\n    // Default case: split on camelCase and capitalize\n    return name\n      .split(/[.~]/)\n      .pop()!\n      .split(/(?=[A-Z])/)\n      .join(' ')\n      .replace(/\\b\\w/g, c => c.toUpperCase());\n  }\n\n  /**\n   * Find paths based on the provided search options\n   * Must be implemented by platform-specific adapters\n   *\n   * @returns Promise resolving to array of path info objects\n   */\n  abstract findPaths(): Promise<PathInfo[]>;\n}\n"]}