Use falafel to rewrite require'd modules in node.
npm install require-falafelRequire-Falafel
===============
!Node.js CI 
**Use falafel to rewrite require'd
modules in node.**
Hook into node's require command to rewrite the module's AST (in memory) before
loading.
Author: Olli Jones
License: MIT
``zsh`
npm install require-falafel --save
Falafel uses
Acorn to transform a
JavaScript AST.
Require-falafel hooks into node's require method in order to transform the AST
of modules as they're loaded.
For example, if we have a library "lib-7" which makes web requests with an
unhelpful user-agent string:
`JavaScript`
const fetch = require("node-fetch");
module.exports = {
get: function() {
fetch("https://www.example.com", {
headers: { "User-Agent": "lib-7" },
})
}
}
This code snippet contains lots of
AST nodes including 4
Literals. We can
see these Literal nodes will be:
`JSON`
{
"type": "Literal",
"value": "node-fetch"
}
{
"type": "Literal",
"value": "https://www.example.com"
}
{
"type": "Literal",
"value": "User-Agent"
}
{
"type": "Literal",
"value": "lib-7"
}
Falafel provides node.source() and node.update(s) methods, so if we wanted"lib-7"
to replace the literal, to provide a better user-agent string for
tracking calls to the API from our new client, we can write a transform method
like:
`JavaScript${source} + "-github.com/ojj11/require-falafel"
const transform = function (node) {
// only change the right literal:
if (node.type == "Literal" && node.value == "lib-7") {
// node.source() will be "lib-7"
let source = node.source();
// we can update the source code (this is quoted JavaScript):
source = ;`
// then we can update the AST node:
node.update(source);
}
}
We can use this method along with RequireFalafel.INCLUDE_NODE_MODULES, toRequireFalafel
make an instance of that we can apply to a block of code thatrequire
includes the statements for lib-7 that we want to transform:
`JavaScript
// wrap our code with a transformation before requiring the library:
const RequireFalafel = require("require-falafel");
const requireFalafel = new RequireFalafel(
RequireFalafel.INCLUDE_NODE_MODULES,
transform);
requireFalafel.applyForBlock(function() {
// require-ing inside .applyForBlock will swap the internals of require to
// apply falafel as the library is loaded:
const lib7 = require("lib-7");
// calling the library will use "lib-7-github.com/ojj11/require-falafel" as the
// user-agent now.
lib7.get();
});
`
Whilst this example is contrived, it is hopefully relatively straight-forward
to see how this library could be used to instrument code as it's loaded in a
test pass, or to enable certain developer flags in a development or staging
environment.
Load require-falafel:
``
const RequireFalafel = require("require-falafel");
Creates a new transformation for require methods, given a typeOfReplacementtransform
and method, for example:
`javascript${source} + "-github.com/ojj11/require-falafel"
const requireFalafel = new RequireFalafel(
RequireFalafel.INCLUDE_NODE_MODULES,
function (node) {
if (node.type == "Literal" && node.value == "lib-7") {
let source = node.source();
source = ;`
node.update(source);
}
});
typeOfReplacement should be one of:
- ['/absolute/paths/to/files.js', require.resolve('module-names')] willrequire.resolve
transform only the absolute paths specified in an array. Use
to get the absolute paths of libraries.RequireFalafel.INCLUDE_NO_NODE_MODULES
- , will transform ./ and ../RequireFalafel.INCLUDE_FIRST_LEVEL_NODE_MODULES
imports, but will not transform any npm modules in node_modules folders.
Only available in node v11+.
- same as above, but will./
transform only the top level of node_modules that are imported from or../
code. Only available in node v11+.RequireFalafel.INCLUDE_NODE_MODULES
- the most liberal, will
transform all require calls, even those inside node_modules
Runs the given block, replacing require calls to load code transformed
through the falafel transformer given on construction.
At the end of the block, resets the require method and clears any loadednode
modules from 's cache, so that a fresh require will get the correct
module.
For example:
`JavaScript
requireFalafel.applyForBlock(function() {
const module2 = require("module2");
// module2 will be transformed and loaded
});
const module2 = require("module2");
// module2 will be re-loaded, but not transformed because it's outside of the
// block
`
This method _will_ work async functions, but the require hook will continue to
apply until await is called:
`JavaScript
// always immediately await:
await requireFalafel.applyForBlock(async function() {
const module2 = require("module2");
// module2 will be transformed and loaded
});
const module2 = require("module2");
// module2 will be re-loaded, but not transformed because await has alreadyapplyForBlock
// been called on `
For cases where supplying a block won't work, use replaceRequire, like so:
`JavaScript
requireFalafel.replaceRequire();
const transformedModule2 = require("module2");
// module2 will be transformed and loaded
requireFalafel.restoreRequire();
const untransformedModule2 = require("module2");
// module2 will be re-loaded, but not transformed because we restored the
// require method
`
Opposite of requireFalafel.replaceRequire() - restores the normal operation ofrequire`.