Search code examples
babeljsgenerategeneratorgenerate

Error: expected file.path to export a function or instance


I creating a generator plugin named generate-swap-project for the generate generator tool.

Let's first see:

The master branch works fine and tests pass on travis AND on local dev host. Tests are run by the following yarn script (on master):

$ yarn test

However in the PR #2 Resolve #1 "Convert to ESNext/StandardJS code style", I made the following changes:

  • converted ES5 codebase to ESNext
  • moved codebase to src/lib and src/tests
  • added a generator.js file a t root level that just requires ./dist/lib/generator.js
  • added yarn scripts: clear + lint + build + test (cf. Readme section about the build pipeline)

Ref. to the branch 1-convert-to-standard-code-style

Tests are run by the following yarn script (on branch 1-convert-to-standard-code-style):

$ yarn travis

or (its alias)

$ yarn pipeline

that is task sequence for yarn clear && yarn lint && yarn build && yarn test

But one test fails (1 test fails for 14 test pass) with a strange error: Error: expected file.path to export a function or instance:

$ yarn pipeline
yarn run v1.3.2
$ yarn clear && yarn lint && yarn build && yarn test
$ yarn rimraf build dist
$ /home/remi/d/dev/generate-swap-project/node_modules/.bin/rimraf build dist
$ yarn lint:esnext
$ yarn standard src/*.js src/**/*.js
$ /home/remi/d/dev/generate-swap-project/node_modules/.bin/standard 'src/*.js' src/lib/generator.js src/tests/plugin.js src/tests/test.js
$ yarn build:lib && yarn build:tests && yarn build:docs
$ yarn babel src/lib/ --out-dir dist/lib --source-maps
$ /home/remi/d/dev/generate-swap-project/node_modules/.bin/babel src/lib/ --out-dir dist/lib --source-maps
src/lib/generator.js -> dist/lib/generator.js
$ yarn babel src/tests/ --out-dir dist/tests --source-maps
$ /home/remi/d/dev/generate-swap-project/node_modules/.bin/babel src/tests/ --out-dir dist/tests --source-maps
src/tests/plugin.js -> dist/tests/plugin.js
src/tests/test.js -> dist/tests/test.js
$ echo WARNING: No documentation build available yet
WARNING: No documentation build available yet
$ yarn mocha dist/tests/**/*.js
$ /home/remi/d/dev/generate-swap-project/node_modules/.bin/mocha 'dist/tests/**/*.js'


  generate-swap-project
    plugin
      ✓ should add tasks to the instance (80ms)
      ✓ should only register the plugin once

  generate-swap-project
    tasks
      ✓ should extend tasks onto the instance
      ✓ should run the `default` task with .build (186ms)
      ✓ should run the `default` task with .generate
    swap-project (CLI)
X =>  1) should run the default task using the `generate-swap-project` name (global install)
      ✓ should run the default task using the `swap-project` generator alias (local generator.js)
    swap-project (API)
      ✓ should run the default task on the generator
      ✓ should run the `swap-project` task
      ✓ should run the `default` task when defined explicitly
    sub-generator
      ✓ should work as a sub-generator
      ✓ should run the `default` task by default
      ✓ should run the `generator:default` task when defined explicitly
      ✓ should run the `generator:swap-project` task
      ✓ should work with nested sub-generators
      ✓ should run tasks as a sub-generator


  15 passing (1s)
  1 failing

  1) generate-swap-project
      swap-project (CLI)
        should run the default task using the `generate-swap-project` name (global install):
    Error: expected file.path to export a function or instance
      at Env.get (node_modules/base-env/lib/file.js:256:11)
      at Env.invoke (node_modules/base-env/lib/env.js:117:19)
      at Generate.<anonymous> (node_modules/base-generators/lib/generator.js:62:30)
      at Generate.getGenerator (node_modules/base-generators/index.js:157:22)
      at Object.exports.process (node_modules/base-generators/lib/tasks.js:127:24)
      at node_modules/base-generators/lib/tasks.js:86:23
      at Array.reduce (<anonymous>)
      at exports.parse (node_modules/base-generators/lib/tasks.js:85:15)
      at Generate.generate (node_modules/base-generators/index.js:490:21)
      at Generate.generate (node_modules/base-generators/index.js:463:23)
      at Context.<anonymous> (dist/tests/test.js:87:11)



error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Here is the travis config

{
  "sudo": false,
  "language": "node_js",
  "node_js": "lts/carbon",
  "script": [
    "npm link",
    "npm install --global generate .",
    "yarn travis"
  ],
  "group": "stable",
  "dist": "trusty",
  "os": "linux"
}

And here is:

I can't understand why that test (the one that runs the generator in CLI mode) fails after ESNext convertion and babel transpilation.

What's wrong with my PR ?


Solution

  • That bug is indeed related to the consequences of the babel transpilation.

    The file generator.js at the root level directory use CommonJS module loading, that's required by the direct call by the global generate binary.

    Here is the code of ./generator.js:

    module.exports = require('./dist/lib/generator')
    

    But:

    • since the module ./dist/lib/generator.js is the result of a babel transpilation of ./src/lib/generator.js, that exports the generator as a default anonymous function,
    • and since the module ./generator.js is a CJS module and use require()

    then the required module is not the exported generator function but an object which contains a property default; and the value of this property is the generator function.

    Thus, the correct way to implement ./generator.js is as following:

    module.exports = require('./dist/lib/generator').default
    

    That's all!

    Here is the PR that fix the issue, and here is the passing travis build for that PR.