How does the coffee-script module work? - node.js

Out of curiosity how does the coffee-script module handle require 'xxx'?
It must be compiling the required file before node can load it... Does it have a specific handling for the 'require' function?
Thanks.

It looks like that's all handled right here:
https://github.com/jashkenas/coffee-script/blob/master/src/extensions.coffee
Which takes advantage of node's ability to register extensions that runs a callback when loaded. This is now deprecated, it seems, but the functionality is still present and working.
It does other stuff too, including some gnarly monkeypatching, but here's the most relevant snippet:
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
answer = CoffeeScript._compileFile filename, false
module._compile answer, filename
# If the installed version of Node supports `require.extensions`, register
# CoffeeScript as an extension.
if require.extensions
for ext in CoffeeScript.FILE_EXTENSIONS
require.extensions[ext] = loadFile

So if I have a coffee file with the line
x = require './ls.coffee'
and run it directly with coffee, e.g. coffee foo.coffee, ls.coffee is loaded with the coffee extension (compiled and run).
But if I compile that script coffee -c foo.coffee, and run it with node, node foo.js, I get an error. Node no longer has the require extension set, and all it sees is the Coffeescript code.

Related

Ignore filename extension for child_process fork using node-dev and Typescript

I have a project written in Typescript, and I'm using node-dev alongside ts-node in my local enviroment for development. I'm using child_process's fork method to instantiate a subprocess, like so:
fork(path.join(__dirname, './worker.ts'));
This works fine, and I can even set breakpoints in VS Code for the worker.
The problem is that when building (transpiling) my project, a MODULE_NOT_FOUND exception is thrown because worker.ts turned into worker.js. Initially, mi idea was to omit the file extension when forking (fork(path.join(__dirname, './worker'));), but if I do so, when running the project with node-dev, it throws a MODULE_NOT_FOUND because it can't resolve the file if the extension is not present.
Is there any workaround for this? Maybe an extra configuration option for node-dev?
I'm on Windows 10 using node v12.22.1
A simple solution I suggest would be to read in the current file type. The compiled files should end with ".js" while the source files end with ".ts". Using the path.extname methode in combination with __filename you can easily extract that file extension and simply concat it to your file name.
fork(path.join(__dirname, './worker' + path.extname(__filename)));

how to require a .js file in node repl

so i usually use ruby irb, and I can pull .rb files I wrote into the console environment by running
load './script.rb'
and then all of the functions I wrote in script.rb will be available.
I cannot figure out for the life of me how to do this in the node "console" environment!
You can load JavaScript files using the require function. The following example assume that the Node.js process was started at the directory where your file is located.
require('./script.js');
This will execute the contents of the file.
If you have exported functions or objects, you can assign them to a variable and use them later.
const myFunction = require('./script.js').myFunction;
myFunction();
Like many other development frameworks/languages, Node has a Modules/Package System which, is a CommonJS variant. To load a Module use require(). The usage of require() is the same when running JavaScript files or running in the REPL.
You can require Node Core Modules, NPM Installed Packages or your own local modules. When loading NPM Packages specified in a package.json or a local module, Node will load them from the Current Working Directory(CWD), you can check this using process.cwd(). The CWD will be set to the absolute path of the directory you launched the REPL from.
You can launch the REPL via running node in your CLI and require your packages like below.
// Core Package
const os = require('os')`
console.log(os)
// NPM Package
const moment = require('moment')
console.log(moment)
// Local Package
const myPackage = require('./myPackage')
console.log(myPackage)
You can also pre-require module(s) using the -r flag when running node. The below will launch the Node REPL with the os package preloaded. You can then access the os package using the variable os
node -r os
console.log(os)
In the future, Node may also support ECMAScript Modules (ie. import). You can read more detailed info about that in the Enhancement Proposal.

How to I run in nodejs a javascript file produced by haste?

If I have a file, hello.hs:
main = putStrLn "Hello, World!"
I can compile it to hello.js using haste command:
hastec hello.hs
How do I run the result hello.js file under nodejs?
By default, Haste's main is set to execute when the browser's onload event fires. This obviously makes no sense for Node, so you need to pass the --onexec flag to Haste when compiling your program:
$ hastec --onexec hello.hs
Haste uses Node to run its test suite in this way. Note, however, that with the exception of writing to standard output (like putStrLn), Haste does not map system operations (file IO, etc.) to Node equivalents. If you're writing an application that needs to interact with the OS, you're better off using vanilla GHC.
Update:
Thank you, and good answer. To recap, if you want to compile and run hello.hs under node, the two lines would be:
hastec --onexec hello.hs
node hello.js
haste doesn't know about node, so the .js files in produces doesn't export anything.
You need to somehow augment the .js file to export the functionality that you want, namely you need to export the hasteMain() function.
You may try the --with-js command line option to hastec
Or you may simply append the following line to the end of your hello.js file:
module.exports = hasteMain;
Once you do that, you can load hello.js as a module using require and run the code:
hasteMain = require('./hello.js');
hasteMain();
You may also want to look at ghcjs. The React team recently moved one of the modules from haste to ghcjs

How does require work when calling node module directly?

When calling a node module directly, e.g. $ ./node_modules/.bin/webpack -d, how is the module aware of how to handle any require functions?
I understand how the require function works, but I'm confused where it is defined.
I had assumed that using something like $ npm start would give context to handle require, but how does Node get involved (and define how to handle require) when the module is called directly?
You're not calling the module directly, you're calling an executable that got installed as part of a package.
That executable runs a full Node interpreter, with the contents of the executable file as the script.
Basically, it's similar to running this on the command line:
node ./node_modules/.bin/webpack

CoffeeScript source maps for nodeJS development

Now that CoffeeScript supports the new Source Map hotness, I was wondering if I can also use the source maps not just in my browser, but on the command line while developing my nodeJS apps.
I want the JS compiler to give me more useful error traces where the lines actually match with my coffeescript files instead of compiled JS files.
The source-map-support module does this, just install the module and put this at the top of your code:
require('source-map-support').install()
Now with CoffeeScript 1.6.2 it just "works" if you run your app with the coffee command :)
Until coffee-script gets some better support for require(), try this:
https://npmjs.org/package/coffee-script-mapped

Resources