text: const slash = require(`slash`)
  const path = require(`path`)
  const fs = require(`fs-extra`)
  const mime = require(`mime`)
  const prettyBytes = require(`pretty-bytes`)
  
  const md5File = require(`bluebird`).promisify(require(`md5-file`))
  const { createContentDigest } = require(`./fallback`)
  
  exports.createFileNode = async (
    pathToFile,
    createNodeId,
    pluginOptions = {}
  ) => {
    const slashed = slash(pathToFile)
    const parsedSlashed = path.parse(slashed)
    const slashedFile = {
      ...parsedSlashed,
      absolutePath: slashed,
      // Useful for limiting graphql query with certain parent directory
      relativeDirectory: path.relative(
        pluginOptions.path || process.cwd(),
        parsedSlashed.dir
      ),
    }
  
    const stats = await fs.stat(slashedFile.absolutePath)
    let internal
    if (stats.isDirectory()) {
      const contentDigest = createContentDigest({
        stats: stats,
        absolutePath: slashedFile.absolutePath,
      })
      internal = {
        contentDigest,
        type: `Directory`,
        description: `Directory "${path.relative(process.cwd(), slashed)}"`,
      }
    } else {
      const contentDigest = await md5File(slashedFile.absolutePath)
      const mediaType = mime.getType(slashedFile.ext)
      internal = {
        contentDigest,
        type: `File`,
        mediaType: mediaType ? mediaType : `application/octet-stream`,
        description: `File "${path.relative(process.cwd(), slashed)}"`,
      }
    }
  
    // Stringify date objects.
    return JSON.parse(
      JSON.stringify({
        // Don't actually make the File id the absolute path as otherwise
        // people will use the id for that and ids shouldn't be treated as
        // useful information.
        id: createNodeId(pathToFile),
        children: [],
        parent: null,
        internal,
        sourceInstanceName: pluginOptions.name || `__PROGRAMMATIC__`,
        absolutePath: slashedFile.absolutePath,
        relativePath: slash(
          path.relative(
            pluginOptions.path || process.cwd(),
            slashedFile.absolutePath
          )
        ),
        extension: slashedFile.ext.slice(1).toLowerCase(),
        size: stats.size,
        prettySize: prettyBytes(stats.size),
        modifiedTime: stats.mtime,
        accessTime: stats.atime,
        changeTime: stats.ctime,
        birthTime: stats.birthtime,
        ...slashedFile,
        ...stats,
      })
    )
  }
  