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
Related
I recently discovered that, whenever I try to to execute a node script like that:
"run-my-script": "node ./folder/function.js executeFunction $ARG"
It seem that using a script with node causes troubles with ES6 imports.
If I run a basic script like that I get this error:
SyntaxError: Cannot use import statement outside a module
My running command line look like that:
ARG=myArg npm run run-my-script
Like if it was impossible for meteor to run a node script outside without the need to transpile code to ES6 first.
All my modules are designed by ES6 modules approach:
import { SchemaBuyers } from './schema';
I don't want to specify type=module inside my package.json because first of all, it's not necessary, I don't have compilation errors when building the apps, ony when running pure node script, and secondly it would require to rename all my files extentions to .mjs for example.
Thank you very much !
You can use node.js's --input-type option for this if you pipe the file into it:
cat test.js | node --input-type=module
Or in your case:
"run-my-script": "cat ./folder/function.js | node --input-type=module executeFunction $ARG"
This assumes that the code in function.js will parse the provided arguments.
I am wondering can I compile a nodejs file from mytestfile.js to mytestfile so I can run it on linux like this ./mytestfile ?
Thank you for your time
Add the following line to the very top of the .js file:
#!/usr/bin/env node
You might have to change the file permission and make it an executable:
chmod +x mytestfile.js
Example mytestfile.js:
#!/usr/bin/env node
// Grab provided args.
const [,, ...args] = process.argv
// Print hello world provided args
console.log(`Hello World ${args}`)
There are a couple of very good and well maintained packages that do that.
I can't tell you which is better. Try both pkg and nexe
The closest you might get to acheiving your goal is to create a self-executing Javascript bytecode wrapper.
A project that does this is pkg
It somehow creates a self-contained binary executable from Javascript, including module dependencies and asset files and produces a self-contained executable.
Installation and use is easy:
$ npm install -g pkg
$ pkg index.js -o my-program
$ ./my-program
My understanding is that this binary contains nodejs bytecode. It also appears that you can cross-compile.
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
It's possible to use coffeescript files without compiling it on node, not directly of course but after importing "cofffee-script/register". I am wondering though if it's possible to feed coffeescript file to node directly, forcing it to import "coffee-script/register" by default? so I could do this from the command line
node debug my-app.coffee
Maybe somehow tweaking require.cache?
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.