import getFileMetadata from 'file-metadata'

/**
 * Attempts to determine if the provided path is an application bundle or not.
 *
 * macOS differs from the other platforms we support in that a directory can
 * also be an application and therefore executable making it unsafe to open
 * directories on macOS as we could conceivably end up launching an application.
 *
 * This application uses file metadata (the `mdls` tool to be exact) to
 * determine whether a path is actually an application bundle or otherwise
 * executable.
 *
 * NOTE: This method will always return false when not running on macOS.
 */
export async function isApplicationBundle(path: string): Promise<boolean> {
  if (process.platform !== 'darwin') {
    return false
  }

  const metadata = await getFileMetadata(path)

  if (metadata['contentType'] === 'com.apple.application-bundle') {
    return true
  }

  const contentTypeTree = metadata['contentTypeTree']

  if (Array.isArray(contentTypeTree)) {
    for (const contentType of contentTypeTree) {
      switch (contentType) {
        case 'com.apple.application-bundle':
        case 'com.apple.application':
        case 'public.executable':
          return true
      }
    }
  }

  return false
}

import { execFile } from 'child_process'
import { promisify } from 'util'

const execFileP = promisify(execFile)

/**
 * Attempts to determine if the provided path is an application bundle or not.
 *
 * macOS differs from the other platforms we support in that a directory can
 * also be an application and therefore executable making it unsafe to open
 * directories on macOS as we could conceivably end up launching an application.
 *
 * This application uses file metadata (the `mdls` tool to be exact) to
 * determine whether a path is actually an application bundle or otherwise
 * executable.
 *
 * NOTE: This method will always return false when not running on macOS.
 */
export async function isApplicationBundle(path: string): Promise<boolean> {
  if (process.platform !== 'darwin') {
    return false
  }

  // Expected output for an application bundle:
  // $ mdls -name kMDItemContentType -name kMDItemContentTypeTree /Applications/GitHub\ Desktop.app
  // kMDItemContentType     = "com.apple.application-bundle"
  // kMDItemContentTypeTree = (
  //     "com.apple.application-bundle",
  //     "com.apple.application",
  //     "public.executable",
  //     "com.apple.localizable-name-bundle",
  //     "com.apple.bundle",
  //     "public.directory",
  //     "public.item",
  //     "com.apple.package"
  // )
  const { stdout: xml } = await execFileP('mdls', [
    ...['-name', 'kMDItemContentType'],
    ...['-name', 'kMDItemContentTypeTree'],
    path,
  ])

  const probableBundleIdentifiers = [
    'com.apple.application-bundle',
    'com.apple.application',
    'public.executable',
  ]

  return probableBundleIdentifiers.some(id => xml.includes(`"${id}"`))
}

Replace file-metadata with custom execFile implementatation
Replace file-metadata with custom execFile implementatation
