npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

require-hacker

v3.0.1

Published

Provides a hooking mechanism for Node.js require() calls

Downloads

39,184

Readme

require-hacker

npm version npm downloads build status coverage

Is a small helper module providing tools for instrumenting Node.js require() calls.

Topics

What it does and why is it needed?

Standard Node.js require() calls simply loaded javascript files from disk and evaluated them.

Some time after various hackers hacked the Module module and various solutions emerged such as coffee-script/register and babel-core/register allowing everyone to require() code written in any language out there (coffeescript and ES7 in case of the aforementioned "require hooks").

This module provides a tool to perform such tricks along with a possibility to also intercept require() calls not just for specific file extensions but for an arbitrary abstract path. Consider, for example, require("http://thor.onion/module?user=123") or require("春秋左傳·僖公二十二年"), whatever. Who might need this? You never know.

Installation

$ npm install require-hacker --save

Usage

Something basic

import require_hacker from 'require-hacker'
import fs from 'fs'

// mount require() hook
const hook = require_hacker.hook('txt', path =>
{
  return `module.exports = "${fs.readFileSync(path).replace(/"/g, '\"')}"`
})

// will output text file contents
console.log(require('./test.txt'))

// unmount require() hook
hook.unmount()

// will throw "SyntaxError: Unexpected token ILLEGAL"
require('./test without hook.txt')

Something unusual

const hook = require_hacker.global_hook('network', path =>
{
  if (!path.starts_with('http://xhamster.com'))
  {
    return
  }

  // returns javascript module source code, something like:
  //
  // "module.exports =
  //  {
  //    category   : 'redhead',
  //    videos     : [12345, 12346, 12347],
  //    unsubscribe: function()
  //    {
  //      http.post('http://xhamster.com/unsubscribe', { user: 123 })
  //    }
  //  }"
  //
  const source = synchronous_http.get(path)
  return { source, path }
})

const readheads = require('http://xhamster.com/category/redhead')
readheads.unsubscribe()

Or

const hook = require_hacker.global_hook('database', path =>
{
  if (!path.starts_with('postgresql://'))
  {
    return
  }

  // returns javascript module source code, something like:
  //
  // "module.exports =
  //  {
  //    words: ['a', 'b', 'c']
  //    sum: function()
  //    {
  //      return words.join('')
  //    }
  //  }"
  //
  const schema = path.substring(0, 'postgresql://'.length)
  const source pg.sql(`select * from ${schema}.generate_javascript()`)
  return { source, path }
})

const summator = require('postgresql://summator')
console.log(summator.sum())

And don't ask me what for.

Configuration

To see debug logs in the console one can use this code

require_hacker.log.options.debug = true

API

.hook(file_extension, resolve)

Will intercept all require() calls for paths with this file_extension and reroute them to the resolve function. The require()d path must exist in the filesystem, otherwise an exception will be thrown: Cannot find module.

Returns an object with .unmount() method which unmounts this require() hook from the system.

The resolve function takes two parameters:

  • the path which is require()d
  • the module in which the require() call was originated (this module parameter can be used for require_hacker.resolve(path, module) function call)

The resolve function must return either a valid CommonJS javascript module source code (i.e. "module.exports = ...", etc) or it can simply return nothing and in that case it will skip this hook.

.global_hook(meaningful_id, resolve, [options])

Can intercept all require() calls. The behaviour is controlled by precede_node_loader option:

  • when it's true (default) it will intercept all require() calls before they are passed to the original Node.js require() loader
  • when it's false it will intercept only those require() calls which failed to be resolved by the original Node.js require() loader

Returns an object with .unmount() method which unmounts this require() hook from the system.

The resolve function takes two parameters:

  • the path which is require()d (e.g. a relative one)
  • the module in which the require() call was originated (this module parameter can be used for require_hacker.resolve(path, module) function call)

The resolve function must return either undefined (in which case it will skip this hook and proceed as normal) or an object { source, path } where

  • source is a valid CommonJS javascript module source code (i.e. "module.exports = ...", etc)
  • path is the absolute path of the path argument passed to this require() function (which could be relative). This returned path is only gonna matter if require()ing some other relative path from the source being returned (because it would get resolved against this absolute path).

.resolver(resolve)

Can intercept all require(path) calls and tamper with the path modifying it if needed (this process is called "resolving").

Returns an object with .unmount() method which unmounts this interceptor.

The resolve function takes two parameters:

  • the path which is require()d.
  • the module in which the require() call was originated (this module parameter can be used for require_hacker.resolve(path, module) function call)

The resolve function must either return a real filesystem path to a javascript (or json) file or it can simply return nothing and in that case it will take no effect.

.to_javascript_module_source(anything)

Converts anyting (an undefined, a string, a JSON object, a function, a regular expression - anything) to a valid CommonJS javascript module source code.

.resolve(path, module)

Resolves a requireable path to a real filesystem path to a javascript (or json) file. Resolution is performed relative to the module (javascript file) passed as the second parameter (resolves npm link, global node_modules, etc). It's just an alias to the native Node.js path resolution function. Will throw Error: Cannot find module '...' if the path isn't resolved to an existing javascript (or json) file.

Gotchas

None whatsoever

References

There are various articles on this sort of require() hook trickery on the internets.

How require() actually works

Hooking into Node loader for fun and profit

Contributing

After cloning this repo, ensure dependencies are installed by running:

npm install

This module is written in ES6 and uses Babel for ES5 transpilation. Widely consumable JavaScript can be produced by running:

npm run build

Once npm run build has run, you may import or require() directly from node.

After developing, the full test suite can be evaluated by running:

npm test

When you're ready to test your new functionality on a real project, you can run

npm pack

It will build, test and then create a .tgz archive which you can then install in your project folder

npm install [module name with version].tar.gz

License

MIT