How to fix unresolved function inspection in WebStorm 10 - node.js

I'm using WebStorm 10.
When I use some lib like bluebird that make code like
var foo = require("foo"); // I will call foo.doSomething
Promise.promisifyAll(foo);
foo.doSomethingAsync(...).then(...)
the doSomethingAsync will be marked as unresolved function inspection.
So what can I do something like config *Async in WebStorm to avoid unresolved function mark?

Best solution at the time is use namespace reserving.
Webstorm supports using comments in order to mark stuff as legitimate:
/** #namespace foo.doSomethingAsync */
var foo = Promise.promisifyAll(require('foo'));
foo.doSomethingAsync(...)
.then(...)
This doesn't solve the actual issue, and won't get you suggestions for the arguments when using the function, but it's surely a convenience, helping clean up the insane amount of warnings generated when promisifying.
I hope this helps..

Got a similar issue when working with TypeScript and Angular 2 (following its Heroes tutorial) using ES2015, but for the Promise object.
Promises are part of the Standard Built-in Objects, so I thought that WebStorm 2016 could use the TypeScript definitions and be able to get it, but by default it didn't.
Everything worked except for this.
So, I went to Settings > Languages & Frameworks > JavaScript and changed the JavaScript language version to ECMAScript 6.
I thought that it would not having nothing to do since I was using TypeScript, but it does.
Now the Promise object reference works and links to lib.es6.d.ts, which is an internal WebStorm definition of ES2015 objects for TypeScript.

Related

No code suggestions for global defined variables in VSCode in a node.js server project

I have to deal with a node.js server project that uses global variables for common APIs. For instance in the entry point server.js there is a Firebase variable for the real-time database that is stored like this:
fireDB = admin.database();
I wasn't aware that this is possible and I would consider this a bad approach, but now I have to deal with it.
I'm not really interested to re-write any of the many calls to this variable in all those files, rather I would find a way to make fireDB show me suggestions only by changing this variable or installing an extension.
I tried to define it on top of the file as var fireDB, but then suggestions only work in the same file, not in others.
When I set a dot behind admin.database() the suggestions work, when I write fireDB. I get no suggestions, yet the call seems to be possible. Suggestions need to work in other files, too. How can I get this to work?
WARNING: MAKE SURE YOU UNDERSTAND THE PROBLEMS WITH GLOBALS BEFORE USING THEM IN A PROJECT
The above warning/disclaimer is mostly for anyone starting a new project that might happen across this answer.
With that out of the way, create a new .d.ts file and put it somewhere with a descriptive name. For example, globals.d.ts at the top level of the directory. Then just populate it with the following (I don't have any experience with firebase, so I had to make some assumptions about which module you're using, etc.):
globals.d.ts
import { database } from "firebase-admin";
declare global {
var fireDB: database.Database;
}
IntelliSense should then recognize fireDB as a global of the appropriate type in the rest of your JavaScript project.
Why does this work? IntelliSense uses TypeScript even if you're working with a JS project. Many popular JS packages includes a .d.ts file where typings are declared, which allows IntelliSense to suggest something useful when you type require('firebase-admin').database(), for example.
IntelliSense will also automatically create typings internally when you do something "obvious", e.g. with literals:
const MY_OBJ = { a: 1, b: "hello"};
MY_OBJ. // IntelliSense can already autocomplete properties "a" and "b" here
Global autocompletion isn't one of those "obvious" things, however, probably because of all the problems with global variables. I'd also guess it'd be difficult to efficiently know what order your files will run in (and hence when a global might be declared). Thus, you need to explicitly declare your global typings.
If you're interested in further augmenting the capabilities of IntelliSense within your JS project, you can also use comments to explicitly create typings:
/**
* #param {String[]} arrayOfStrings
*/
function asAnExample(arrayOfStrings) {
arrayOfStrings. // IntelliSense recognizes this as an array and will provide suggestions for it
}
See this TypeScript JSDoc reference for more on that.

How can I fix the "Error: 'default' is not exported by..." when using formdata-node default import?

Summary
I feel like I've hit my head against a wall too many times trying to figure out where I may be going wrong. I have a simple piece of typescript code:
import FormDataI from 'formdata-node'
const c = new FormDataI()
export { c }
That im trying to compile down to umd using rollup and typescript. For some reason, I cant seem to get it to compile correctly and instead receive an error message:
[!] Error: 'default' is not exported by node_modules/formdata-node/lib/FormData.js, imported by index.ts
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module
index.ts (1:7)
Any suggestions as to where I may be going wrong? Here is a sample project that throws the error.
Things I've tried
Playing with various typescript settings such as esModuleInterlop
Playing with the commonjs properties such as requireReturnsDefault
Stepping through the rollup code hoping to find the import error. It appears to not notice the export from formdata-node which is exported using module.exports.default and module.exports
UPDATE
In the case of the above situation, I could simply set it as a global/external since FormData is supported in the browser natively. The question is, why does this error appear at all though?

WebStorm compatibility with exporting of classes

I know that the ES6 export/import syntax is not part of Node.JS yet, so when I write a class in Node.JS, it usually goes something like this:
class Foo {
...
}
module.exports = Foo;
However, I frequently see a slightly more compact version of this:
module.exports = class Foo { ... }
When I write this code in WebStorm it will however complain "expression expected" (it doesn't like the class keyword in an assignment). The file seems to work fine when run with Node (~6.10) though.
Is there a compatibility setting in WebStorm to allow this? The only option I found was an inspection for warning about non-ES6 draft features.
WebStorm has issues resolving members of classes exported this way (see WEB-28158), but the syntax itself is correctly accepted (WebStorm 2017.3.2):
What IDE version do you use? Did you set JavaScript Language Version to ECMAScript 6 in Settings | Languages & Frameworks | JavaScript?
If this doesn't help, try invalidating caches

how can I import json file in typescript

I am using typescript and requirejs. For the most part the amd modules are generated beautifully. I am however stuck with loading using requirejs json or for that matter text plugin.
define(["json!sometextfile.json"], function(myJson)
How can I do this in typescript. I am using TS 1.6 at the moment.
I'm not sure I have understood your question, but I think you want to know how to call require directly without getting a compiler error... for example:
require(["json!sometextfile.json"], function(myJson) {
});
The quick fix for this is to supply a very open definition for the require function:
declare var require: any;
require(["json!sometextfile.json"], function(myJson) {
});
You can improve upon this crude fix by using the full RequireJS type definition from the Definitely Typed project.

Cannot set breakpoint inside function when using require inside closure

Using node-inspector, I'm unable to set breakpoint in the following node.js code. (Content of main.js)
(function() {
require('underscore');
var doSomething = function(callback) {
callback('doSomething Finished');
}
doSomething(function(x) {
console.log(x);
});
}).call(this);
I can easily set a breakpoint on line 2, line 4 or line 8, however no matter how hard I try the debugger won't let me set a break point on line 5 or line 9. To be clear, I'm using the following commands to run node-inspector
node --debug-brk main.js
node-inspector
I also tried to debug in web storm, however the issue persists. If I remove the line require('underscore');, then the problem immediately goes away and I'm able to set break point inside function body again. The problem also goes away if I remove the outermost closure function. It seems that the interaction between require and file level closure is screwing up the node debugging functionality. Has anyone experienced this problem themselves and / or knows any workarounds to be able to break inside function body?
EDIT: My node js version
Tony:~ $ node --version
v0.10.12
Tony:~ $
I ran exactly into the same issue with the same setup.
I've added a breakpoint after the definition of the target-function (that was the only place i could actually add a breakpoint). When the debugger reached that breakpoint and the function was actually defined, i was able to add breakpoints to the actual target-function...
This may not be the answer that you want to hear as it doesn't explain why you can't set any breakpoints, but I would simply remove your require statement from the closure and place it top-level. I would go even further and recommend that you don't use a closure like the one above at all.
The reason is that node uses its own module system, and unlike Javascript in the browser, declaring variables top-level does not pollute the global namespace. This is where require(...) comes in. So, you gain nothing by wrapping your code in an immediately invoked function (unless of course you want your module to be able to run both client side and server side).
I would guess that the reason that you are not able to set any breakpoints is that the V8 runtime is recognizing an unnecessary closure and then optimizing your code for you. The rewritten code may not have the correct source mapping and so breakpoints cannot be set.
So, two suggestions:
require calls are not like regular statements. They are more similar to import statements in Java and are handled specially by the compiler. They should always be top-level in a node file.
No need to wrap your code in an anonymous function when in Node.

Resources