Hyper: require() in .hyper.js config

Created on 7 Jun 2018  路  7Comments  路  Source: vercel/hyper

Hi! I'd like to use require() in my .hyper.js, but I get a ReferenceError when doing so. Could this be added?

My specific use case is the following:

let fs = require('fs');
module.exports = {
    // ...
    shell: (() => {
      let userPath = 'C:\\Users\\niklas\\Applications\\Git\\bin\\bash.exe';
      let systemPath = 'C:\\Program Files\\Git\\bin\\bash.exe';
      if (fs.existsSync(userPath)) return userPath;
      return systemPath;
    })()
};

Eventually, I would like to set some configuration values based on the current platform, too.

馃挰 Feedback Wanted

Most helpful comment

My use case for require would be similar to @jcrben's reason for conditional config based on platform, specifically so that I could have a base config file in my dotfiles repo, which I could extend with platform-specific settings in whatever workstation I set up.

All 7 comments

I did a little investigating into this, and since vm.Script is used (for good reason, safety), common objects such as process and require, are not passed through to the script.

When vm.Script.runInNewContext is called (ref), an object named module is passed in. This is why module does not result in a ReferenceError within the file.

As module is passed in, when the script is executed, and module.exports = {} is called, the module object created outside of the .hyper.js context is modified.

To add require in, it should just be a matter of updating the context for the script to:

script.runInNewContext({ module, require });

However, I believe that this problem may arise again with others asking for access to process or other standard objects and methods.

Adding in module this way also seems like a slight hack as it emulates the global object (ref) without also providing access to the global object directly.

Therefore, I propose the following:

  • pass in a cloned global object (runInNewContext({global: ...global}))
  • pass in the contents of the global object for top-level access (runInNewContext({...global}))

The top-level global contents and the global object should be a reference to one another for consistency.

Objects and methods accessible in the .hyper.js config file would be:

  • clearImmediate
  • clearInterval
  • clearTimeout
  • console
  • exports
  • global
  • module,
  • process
  • require()
  • setImmediate
  • setInterval
  • setTimeout
  • URL
  • URLSearchParams

as per the spec defined here

However, I beg the question as to whether the trade-off for ease of modifying the config is worth the very possible risk of unauthorised code execution. Remember, hyper can have access to sudo

Though adding in these may cause unforeseen issues with specific configuration.

See https://github.com/zeit/hyper/pull/2684#issuecomment-383061219, we're thinking of changing the config to .json to make it even safer.

What's the use case you want to use require inside your config?

sidenote: I personally don't like the idea of moving to json as it doesn't support comments. maybe json.serialize of the module.exports would be better?

I don't really have a use case, but was interested in the idea. The OP wants to check for valid paths with fs.

If we move to JSON config, it will be using https://json5.org/ or similar to allow comments 馃憤

Per @harryparkdotio's comment above, I'd also prefer to have a cloned in global or at minimum, process object in the configuration. I'd like to maintain a consistent single configuration across platforms, and access to the process.platform value would enable the minor customization needed for each.

It seems like moving to a JSON configuration would completely remove the option of having customization per platform (without tiered configuration on multiple levels).

UPDATE: I started a plugin with decorateKeymaps() for the below mentioned use case, altho still ironing out the details - note that this is an undocumented extension point (will try to add docs at some point)

+1 - use case right now is allowing me to configure conditional upon the platform; in my case right now, I want to use the same keys by physical location regardless of actual key value (option, meta, etc)

My use case for require would be similar to @jcrben's reason for conditional config based on platform, specifically so that I could have a base config file in my dotfiles repo, which I could extend with platform-specific settings in whatever workstation I set up.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anthonyettinger picture anthonyettinger  路  3Comments

sarneeh picture sarneeh  路  3Comments

alejandrofloresm picture alejandrofloresm  路  3Comments

aem picture aem  路  3Comments

yvan-sraka picture yvan-sraka  路  3Comments