Repository: gatsbyjs/gatsby
File: packages/gatsby-source-filesystem/src/extend-file-node.js (JavaScript)

Code before:

  return {
    publicURL: {
      type: GraphQLString,
      args: {},
      description: `Copy file to static directory and return public url to it`,
      resolve: (file, fieldArgs, context) => {
        const details = getNodeAndSavePathDependency(file.id, context.path)
        const fileName = `${file.internal.contentDigest}/${details.base}`

        const publicPath = path.join(
          process.cwd(),
          `public`,
          `static`,
          fileName
        )

        if (!fs.existsSync(publicPath)) {
          fs.copy(
            details.absolutePath,
            publicPath,
            { dereference: true },
            err => {
              if (err) {
                // Capture error within new Reporter API
                reporter.panic({
                  id: `TBD`,
                  context: {
                    sourceMessage: `error copying file from ${details.absolutePath} to ${publicPath}`,
                  }
                }, err)
              }
            }
          )
        }

        return `${pathPrefix}/static/${fileName}`
      },
    },
  }
}


Review comment (refactor):
Ok, this looks good so far! `reporter` is passed in via node APIs and is used correctly with the two args on reporter.panic 👍 

What's missing now is an `errorMap` in the gatsby-node.js file of this source plugin, like here: https://github.com/gatsbyjs/gatsby/blob/unified-routes/ga/packages/gatsby-plugin-page-creator/src/gatsby-node.ts#L204-L206

Check for the existence of this API before calling it.

Then you could create an `error-utils` file like here (without the TS stuff): https://github.com/gatsbyjs/gatsby/blob/unified-routes/ga/packages/gatsby-plugin-page-creator/src/error-utils.ts

The ID should be 5-digit and can be totally random, just start with a number and count up. Then, with the prefixId helper every ID should be prefixed with the name of the plugin (`gatsby-source-filesystem`), e.g. like here: https://github.com/gatsbyjs/gatsby/blob/unified-routes/ga/packages/gatsby-plugin-page-creator/src/derive-path.ts#L44-L49

This way every ID is prefixed (also on old versions). This is only for backward-compatibility. Normally you would only need to define the errorMap and use the normal ID.

The errorMap itself will hold the ID (not prefixed) and the `text`, `level`, `type` and `category`.

Code after:
  pathPrefix = ``,
  reporter,
}) => {
  if (type.name !== `File`) {
    return {}
  }

  return {
    publicURL: {
      type: GraphQLString,
      args: {},
      description: `Copy file to static directory and return public url to it`,
      resolve: (file, fieldArgs, context) => {
        const details = getNodeAndSavePathDependency(file.id, context.path)
        const fileName = `${file.internal.contentDigest}/${details.base}`

        const publicPath = path.join(
          process.cwd(),
          `public`,
          `static`,
          fileName
        )

        if (!fs.existsSync(publicPath)) {
          fs.copy(
            details.absolutePath,
            publicPath,
            { dereference: true },
            err => {
              if (err) {
                reporter.panic(
                  {
                    id: prefixId(CODES.MissingResource),
                    context: {
                      sourceMessage: `error copying file from ${details.absolutePath} to ${publicPath}`,
                    },
                  },
                  err
                )
              }
            }
          )
        }

        return `${pathPrefix}/static/${fileName}`
      },
    },
  }
}