{"version":3,"sources":["../index.ts"],"sourcesContent":["import cp from 'node:child_process';\nimport path from 'node:path';\nimport util from 'node:util';\n\nconst execAsync = util.promisify(cp.exec);\n\ninterface FileDialogOptions {\n  multiple?: boolean;\n  checkFileExists?: boolean;\n  filter?: string;\n  title?: string;\n  defaultExtension?: string;\n}\n\ninterface FileDialogResult {\n  files: string[];\n  canceled: boolean;\n}\n\nclass FileDialogError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'FileDialogError';\n  }\n}\n\nconst isCanceled = (v: string): boolean => /cancell?ed/i.test(v);\n\n// Escape special characters for PowerShell\nconst escapeForPowerShell = (str: string): string => {\n  return str.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '`\"').replace(/\\$/g, '`$');\n};\n\nconst buildFilterString = (filter: string): string => {\n  // Handle common filter formats\n  if (filter === '*' || filter === '*.*') {\n    return 'All files (*.*)|*.*';\n  }\n\n  // If it's already in the correct format, return as is\n  if (filter.includes('|')) {\n    return filter;\n  }\n\n  // Convert simple patterns to proper format\n  // e.g., \"*.txt\" becomes \"Text files (*.txt)|*.txt\"\n  const ext = filter.replace('*', '').replace('.', '');\n  if (ext) {\n    return `${ext.toUpperCase()} files (${filter})|${filter}`;\n  }\n\n  return 'All files (*.*)|*.*';\n};\n\nconst checkPowerShellAvailable = async (): Promise<boolean> => {\n  try {\n    const { stdout } = await execAsync('powershell.exe -Command \"echo test\"', {\n      timeout: 5000\n    });\n    return stdout.trim() === 'test';\n  } catch {\n    return false;\n  }\n};\n\nexport const openWindowsFileDialog = async (\n  filepath: string = process.cwd(),\n  options: FileDialogOptions = {}\n): Promise<FileDialogResult> => {\n  if (typeof filepath !== 'string') {\n    throw new FileDialogError('Filepath must be a string');\n  }\n\n  const normalizedPath = path.resolve(filepath);\n  const isPowerShellAvailable = await checkPowerShellAvailable();\n  if (!isPowerShellAvailable) {\n    throw new FileDialogError('PowerShell is not available on this system');\n  }\n\n  const opts: Required<FileDialogOptions> = {\n    multiple: true,\n    checkFileExists: true,\n    filter: '*.*',\n    title: 'Select File(s)',\n    defaultExtension: '',\n    maxTimeout: 5 * 60 * 1000, // 5 minutes\n    ...options\n  };\n\n  const escapedPath = escapeForPowerShell(normalizedPath);\n  const escapedTitle = escapeForPowerShell(opts.title);\n  const filterString = buildFilterString(opts.filter);\n  const pathSeparator = '|<<PATH_SEPARATOR>>|';\n\n  const powershellScript = `\n    try {\n      Add-Type -AssemblyName System.Windows.Forms\n      [System.Windows.Forms.Application]::EnableVisualStyles()\n\n      $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog\n      $OpenFileDialog.Multiselect = ${opts.multiple ? '$true' : '$false'}\n      $OpenFileDialog.InitialDirectory = \"${escapedPath}\"\n      $OpenFileDialog.Filter = \"${escapeForPowerShell(filterString)}\"\n      $OpenFileDialog.CheckFileExists = ${opts.checkFileExists ? '$true' : '$false'}\n      $OpenFileDialog.CheckPathExists = $true\n      $OpenFileDialog.SupportMultiDottedExtensions = $true\n      $OpenFileDialog.Title = \"${escapedTitle}\"\n      $OpenFileDialog.RestoreDirectory = $true\n      ${opts.defaultExtension ? `$OpenFileDialog.DefaultExt = \"${escapeForPowerShell(opts.defaultExtension)}\"` : ''}\n\n      # Ensure dialog appears on top\n      $OpenFileDialog.ShowHelp = $false\n\n      $DialogResult = $OpenFileDialog.ShowDialog()\n\n      if ($DialogResult -eq [System.Windows.Forms.DialogResult]::OK) {\n        foreach ($FileName in $OpenFileDialog.FileNames) {\n          Write-Host \"$FileName${pathSeparator}\"\n        }\n      } else {\n        Write-Host \"CANCELLED\"\n      }\n    } catch {\n      Write-Error $_.Exception.Message\n      exit 1\n    }\n  `;\n\n  return new Promise((resolve, reject) => {\n    const child = cp.spawn(\n      'powershell.exe',\n      ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-WindowStyle', 'Hidden', '-Command', '-'],\n      {\n        windowsHide: true,\n        shell: false\n      }\n    );\n\n    let stdoutData = '';\n    let stderrData = '';\n    let hasResolved = false;\n\n    child.stdout.on('data', data => {\n      stdoutData += data.toString();\n    });\n\n    child.stderr.on('data', data => {\n      stderrData += data.toString();\n    });\n\n    child.on('error', error => {\n      if (!hasResolved) {\n        hasResolved = true;\n        reject(new FileDialogError(`Failed to spawn PowerShell: ${error.message}`));\n      }\n    });\n\n    child.on('close', code => {\n      if (hasResolved) return;\n      hasResolved = true;\n\n      if (code !== 0 && stderrData) {\n        const errorMessage = stderrData.trim();\n        reject(new FileDialogError(`PowerShell error: ${errorMessage}`));\n        return;\n      }\n\n      const output = stdoutData.trim();\n\n      if (isCanceled(output)) {\n        resolve({ files: [], canceled: true });\n        return;\n      }\n\n      const files = output\n        .split(pathSeparator)\n        .map(s => s.trim())\n        .filter(s => s !== '');\n\n      const validFiles = files.filter(f => path.isAbsolute(f));\n      if (validFiles.length !== files.length) {\n        console.warn('Some file paths were not absolute and were filtered out');\n      }\n\n      resolve({ files: validFiles, canceled: false });\n    });\n\n    if (opts.maxTimeout) {\n      // If maxTimeout is set, set timeout to kill the process if it takes too long\n      const timeout = setTimeout(() => {\n        if (!hasResolved) {\n          hasResolved = true;\n          child.kill();\n          reject(new FileDialogError('Dialog timeout after 5 minutes'));\n        }\n      }, opts.maxTimeout);\n\n      child.on('exit', () => {\n        clearTimeout(timeout);\n      });\n    }\n\n    child.stdin.write(powershellScript);\n    child.stdin.end();\n  });\n};\n\nexport const openWindowsFileDialogSync = async (filepath?: string, options?: FileDialogOptions): Promise<string[]> => {\n  const result = await openWindowsFileDialog(filepath, options);\n  return result.files;\n};\n\nexport default openWindowsFileDialog;\n"],"mappings":"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","names":[]}