Version compatibility issue Azure functions' Node and DirectlineJS es6 exports - node.js

End Goal:
To create Azure Function running Botframework-DirectlineJS with binding to Bot (Framework) using DirectLine secret.
Issue:
The above mentioned Botframework-DirectlineJS uses ES6 export and Azure Functions support Node 6.5.0 max doc. Hence the question how to import successfully the DirectlineJS in the index.js file of Azure function?
Error
```
2017-05-23T07:17:45.939 Exception while executing function: Functions.adapter. mscorlib: D:\home\site\wwwroot\adapter\importexportwrapper.js:1
(function (exports, require, module, __filename, __dirname) { import { DirectLine } from 'botframework-directlinejs';
^^^^^^
SyntaxError: Unexpected token import
at Object.exports.runInThisContext (vm.js:76:16)
at Module._compile (module.js:528:28)
at Object.Module._extensions.(anonymous function) [as .js] (D:\home\site\wwwroot\node_modules\node-hook\index.js:73:14)
at Module.load (module.js:473:32)
at tryModuleLoad (module.js:432:12)
at Function.Module._load (module.js:424:3)
at Module.require (module.js:483:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (D:\home\site\wwwroot\adapter\index.js:4:2)
at Module._compile (module.js:556:32).
```
Currently the error was while trying to use npm import-export
Files
index.js
require('import-export');
require ('./importexportwrapper');
let directLine = new DirectLine({
secret: 'DirectlineSecretValue-here'
}
);```
importexportwrapper.js
import { DirectLine } from 'botframework-directlinejs';

Unfortunately it seems like import-export or node-hook doesn't play well with functions / edgejs (the environment we use to run node).
A couple options to try:
use babel to transpile es6 to es5 as a part of your deployment process.
write your function in typescript (index.ts) which will do import transpilation automatically - though this may fail for module dependencies, I haven't tried it out

You have three options: 1) Write your code using ES5, 2) setup a task runner (gulp/grunt/npm scripts) to convert your ES6+ code to ES5 using Babel, or 3) write your code in Typescript and compile it to ES5 via task runner/npm scripts.
The most straight-forward method would be: in your file importexportwrapper.js use require instead of import.
Example:
var directline = require('botframework-directlinejs');
Babel + Gulp Option
Install: npm install --save-dev gulp gulp-babel
Run:
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("default", function () {
return gulp.src("src/app.js") // your source files
.pipe(babel())
.pipe(gulp.dest("dist")); // your compiled output directory
});
Read more about Azure Functions Node.js versions here.

Related

"SyntaxError: Cannot use import statement outside a module" with a npm module

I'm trying to use a npm module (https://github.com/AmyrAhmady/steamdb-js) but when I use the example code,
I got a "SyntaxError: Cannot use import statement outside a module".
This is the example code:
import { Game } from "steamdb-js";
async function main() {
const game = new Game(271590);
await game.fetchData();
const data = await game.parse();
//console.log(data); // This prints out all parsed data, you can use it for easier in-code usage
console.log(game.getGameInfo());
}
main();
and this is the error:
PS C:\Users\user\Desktop\Développement\TEST> node .\index.js
C:\Users\selim\Desktop\Développement\TEST\index.js:1
import { Game } from "steamdb-js";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1116:16)
at Module._compile (internal/modules/cjs/loader.js:1164:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
at Module.load (internal/modules/cjs/loader.js:1049:32)
at Function.Module._load (internal/modules/cjs/loader.js:937:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
Is it my fault or the npm module's fault?
Been a while since this thread was created, but I think it's my responsibility to answer that when it comes to a library that I made.
first of all, example and steamdb-js code is using ES5 standards (such as import and export syntax)
You need to enable those first, you can use latest available Nodejs versions, or use a transpiler; If you are not using Node +v13 or don't know how to do that, here's my recommendation:
Install https://www.npmjs.com/package/esm by using npm i esm in your project workspace
Instead of using node ./index.js, use node -r esm ./index.js
Now everything should work fine and steamdb-js should be able to be """execute"""
I'm putting stress on execute cause there's an issue now, we know steamdb is using CloudFlare, they have "Under Attack" mode enabled and that's an issue that can be bypassed, but the sad part is due to CloudFlare's new changes, I doubt current libraries out there work at the moment, I'll update my library as soon as I find a way.
Thanks!
(My first ever post on Stackoverflow!)
One of the easiest ways is to just add "type": "module" to your package.json file. There's a more in-depth description in the Node Documentation.

ECMAScript Modules On Node.js v11.9.0

I'm trying to use exports and import on Node.js application, So I used the Node.js documentation ECMAScript Modules. But I am getting error
I am using,
v11.9.0
Run command node --experimental-modules app.js
How can I use ES6 export and import in Node.JS ? Preferred me the way that not using any additional package !
Code :
// test.js
module.exports = { one: 1 };
// app.js
import foo from './test.js';
console.log(foo);
Error :
(node:9352) ExperimentalWarning: The ESM module loader is experimental.
/home/Workspace/test/app.js:1
(function (exports, require, module, __filename, __dirname) { import foo from './test.js';
^^^
SyntaxError: Unexpected identifier
at new Script (vm.js:84:7)
at createScript (vm.js:264:10)
at Proxy.runInThisContext (vm.js:312:10)
at Module._compile (internal/modules/cjs/loader.js:694:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
at Function.Module._load (internal/modules/cjs/loader.js:558:3)
at createDynamicModule (internal/modules/esm/translators.js:73:15)
at Object.meta.done (internal/modules/esm/create_dynamic_module.js:40:9)
As the doc says your files need a .mjs extension:
The --experimental-modules flag can be used to enable features for
loading ESM modules.
Once this has been set, files ending with .mjs will be able to be
loaded as ES Modules.
You have to currently use the flag and there is no "seamless" way to use them at the moment other than using a transpiler like babel.
As Quentin says CommonJS files can still use .js extension (you can mix and match).

What is the current simplest way to use ES6 / Import statements etc in Node v 10

I'm fairly new to nodejs. With the evolution of nodejs ( I have just installed v.10 ) what is the current simplest way to use ES6 features ( import statements etc ) in a new nodejs project - that "just works" . I want the least dependencies and the method with the fastest path to "just works".
I am finding the posts on the web a bit confusing.
Babel was installed previously for this sort of thing I understand
Node 10 Says ( Here ) enable using node --experimental-modules my-app.mjs
This post seems quite authoritative , but I think it's about creating packages more than using the syntax.
Please help! I seem to get the following errors for;
import {MagentoAccountApi} from 'js-magento-client';
Error 1:
SyntaxError: Unexpected token {
at new Script (vm.js:74:7)
at createScript (vm.js:246:10)
at Object.runInThisContext (vm.js:298:10)
at Module._compile (internal/modules/cjs/loader.js:646:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
at Function.Module._load (internal/modules/cjs/loader.js:520:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
at startup (internal/bootstrap/node.js:228:19)
If I try renaming the file to have an extension .mjs and load using: node --experimental-modules .\mtest.mjs , then I get this error:
(node:20224) ExperimentalWarning: The ESM module loader is experimental.
file:///F:/node/magento-test/mtest.mjs:1
import {MagentoAccountApi} from 'js-magento-client';
^^^^^^^^^^^^^^^^^
SyntaxError: The requested module 'js-magento-client' does not provide an export named 'MagentoAccountApi'
at ModuleJob._instantiate (internal/modules/esm/module_job.js:89:21)
I don't know if that is a packagage error , or a setup error.
Maybe Babel is still the right / easiest way to make this work..? I guess I don't want to start using something the is going to be deprecated soon.
At present, with the experimental loader, CommonJS interoperability only allows for a single default export. You can't use named exports with existing CommonJS modules, so currently you have to do this:
import Magneto from "js-magento-client";
const { MagentoAccountApi } = Magneto;
Which is not correct, but is in the process of being fixed apparently.
From the NodeJS v10 docs:
When loaded via import these modules will provide a single default
export representing the value of module.exports at the time they
finished evaluating.
import fs from 'fs';
fs.readFile('./foo.txt', (err, body) => {
if (err) {
console.error(err);
} else {
console.log(body);
}
});
All the comments above telling you that it's a bad idea to start out with an experimental feature are 100% on-point. The above is a good example. At some point this is going to change and you'll have to change your code. If you used Babel instead, you wouldn't have this issue.

Unexpected Token * Koa.js

I'm getting a harmony error when trying to run Koa.
Here is the error after I ran my mocha tests, I get this error at the end:
MacBook-Pro$ mocha test
...projects/search-api/node_modules/koa/lib/application.js:179
function *respond(next) {
^
SyntaxError: Unexpected token *
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
Here's my server.js
'use strict';
var supertestKoa = require('supertest-koa-agent');
var app = module.exports = require('koa')(),
port = process.env.PORT || 3000;
supertestKoa(app);
app.listen(port, function(){
console.log('Koa app is listening on port' + port);
});
Let me know if you need anything else from me to help troubleshoot this.
It's failing on the generator function* syntax. Here are a few options to get around this:
If you're using node 0.11 or higher, you'll need to enable es6 generators by running with harmony. Typically I do something like this: node --harmony path/to/mocha.
Alternatively, you can upgrade to io.js, which supports generators and a few other es6 goodies without needing a runtime flag.
One other possibility is running the tests using the babel transpiler. The babel website has detailed instructions how to do that (look for "mocha" on that page). This is probably your best bet if you're still on node 0.10 or lower, which have zero generator support.
This is because of function * in application.js not your node file. function * is a generator function in ES6 (ES2015) http://wiki.ecmascript.org/doku.php?id=harmony%3agenerators. This is the next version of javascript that not all version of browsers/node.js support yet.
There are a couple options here you can transpile that file back to ES5 so that browsers/node.js can understand it. You can also use something like babel to transpile your code back to ES5. You can also set the --harmony flag in node which will allow node to understand and utilize the generator function.

Typescript AMD Modules for Node.js

I have the following Typescript File which i compile with AMD Modules:
import tsmx = module("../TSMX/tsmx");
tsmx.createServer(1337);
which produces the following js:
define(["require", "exports", "../TSMX/tsmx"], function(require, exports, __tsmx__) {
var tsmx = __tsmx__;
tsmx.createServer(1337);
})
When i try to load it in Node.js i get the following error:
(function (exports, require, module, __filename, __dirname) { define(["require
^
ReferenceError: define is not defined
at Object. (C:\DB\Repo\TSMX\TSMX\TSMXTest\app.js:1:63)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3
How to make this work and get "define" defined? I need AMD Modules because i will load some code in the browser.
I come from C# and AS3 where Imports/Namespaces are a lot easier so sorry if this is a amateur question.
EDIT:
As recommended by http://requirejs.org/docs/node.html#nodeModules i added to the top of the file:
if (typeof define !== 'function')
{
var define = require('amdefine')(module );
}
define(function (require)
{
var dep = require('dependency');
return function () { };
});
but this gets placed inside the define call by typescript which makes it useless.
Then i manually placed it outside of the define call which just resulted in an "Cannot find module 'amdefine'" error.
Just an option: You don't need to use AMD on node. Compile your node files separately from your browser files. Use AMD for browser.
If you still want to use AMD on node code this might help: http://nodejs.org/docs/v0.5.0/api/modules.html
I haven't used node yet, but in the browser define / require are defined in a third party library e.g. requirejs : http://requirejs.org/ demo : http://www.youtube.com/watch?v=4AGQpv0MKsA

Resources