VSCode IntelliSense for commonJS modules using path.join() - node.js

In an Adobe CEP panel that I am working on which also uses NodeJS, I have been using the following approach to require other modules:
require('path');
const moduleA = require(path.join(__dirname, "/*PATH-TO*/module_A.js"));
const moduleB = require(path.join(__dirname, "/*PATH-TO*/module_B.js"));
My problem is that VSCode doesn't parse those files and I am not getting IntelliSense autocomplete after requiring those modules.
Is there a way to make IntelliSense work with such code?
--
Note:
That's the only way I could get After-Effects to find those modules, using relative paths gives me errors: Uncaught Error: Cannot find module './module_A'. I have also tried using paths relative to the project folder.
(Alternatively, I would love to know how to make require() work with relative paths in an After-Effects CEP panel, but in this case my project is already full of these requires statements)

Related

How to determine the module system from a node js library code for importing config file

I'm working on adding support for .js config file in a NodeJS library. NodeJS support two module system - ESM & CommonJS - and since javascript files with .js can be treated as an ES Module or a Common JS module based on the what is defined as type parameter in package.json, I'm not able to figure out, how to know that what module system is a user of the library is using. Based on the module system used by the user only I can decide whether to import config using require() or import()
There isn't a good way too know about the module type of the application code form a node module. One workaround that I can think of would be using something like parent-package-json –
import getParent from 'parent-package-json';
const parent = getParent();
const parentModuleType = parent ? parent.type : DEFAULT_MODULE_TYPE;

`require` in VSCode extension: Cannot find module './tool.js'

I'm trying to write a language server based off of the vscode languages server sample.
I have a file at lsp-sample/server/src/tool.js which was generated by an external tool (js_of_ocaml), which I'd like to import in my plugin using require. I do this as follows in lsp-sample/server/src/server.ts:
var tool = require('./tool.js');
However, when I do so, I get the following rutime error:
Cannot find module './tool.js'
If I require using an absolute path, I don't get an error, but obviously that doesn't work for an extension that I'd like to run on multiple computers.
What is the proper path I should be giving to require? What is the "current directory" that I need to define my relative path in relation to?
When using require(), you should not include the file extension. Try
var tool = require('./tool');
instead.

Typescript module import with configuration file

I would to like forge the path to access node_modules with some configuration file. It seems it's not possible to do the thing below, how should I forge my path then?
The aim is to write absolute path to some node_modules ( cause some files are splitted so this is needed).
import someFileSettings from "./../../models/someFileSettings";
import * as request from JSON.stringify(someFileSettings .somePathIneed+"request");
No, it's not possible, because TypeScript modules follow the standard ES6 modules. To do that, there is a module loader API, based on promises.
Here is the explanation from the book of Dr. Axel Rauschmayer:
16.9.1 Can I use a variable to specify from which module I want to import?
The import statement is completely static: its module specifier is always fixed. If you want to dynamically determine what module to load, you need to use the programmatic loader API:
const moduleSpecifier = 'module_' + Math.random();
System.import(moduleSpecifier)
.then(the_module => {
// Use the_module
})
... but, notice this warning:
The module loader API is not part of the ES6 standard

TypeScript: Unexpected reserved word

I have a project in WebStorm IDE & Node.js. I created a file named "mongo-manager.ts" which I used in the routes\index.js file. It worked seamlessly.
Then I did 2 things:
WebStorm had always asked me whether or not to compile TypeScript to JavaScript and I had always ignored it, but then once I clicked on "yes" and since then after solving some errors it's compiling now ts files successfully to js.
I converted index.js into index.ts and now I still have index.js which is an output of the compilation.
Ever since then, when I try to run my app (using the triangular green button in WebStorm which in turn uses the command line: "C:\Program Files (x86)\JetBrains\WebStorm 11.0.1\bin\runnerw.exe" "C:\Program Files\nodejs\node.exe" bin\www), I get this error:
import mongodb = require('mongodb');
^^^^^^
SyntaxError: Unexpected reserved word
Now, there's no specific problem with the "import" statement because if I omit it, the next non JavaScript statement throws the same exception. It just tries to treat TypeScript like it was JavaScript.
I've found these questions:
Typescript: unexpected reserved word in PHPStorm,
Unable to import in typescript file in nodejs
They suggest either to use "tsc" rather than node.exe, or to make sure that I run with node.exe the js file rather than the ts file.
Now the thing is that the file that node.exe runs directly is "www" which is a JavaScript file and in turn calls app.js which is still JavaScript, but later the files index.ts and mongo-manager.ts are called, so I have a hybrid of both js and ts.
And another and most important thing is that my code has already worked seamlessly even though it's hybrid and without taking any of the suggestions in these questions, until I answered WebStorm "yes" to the question whether to compile TypeScript to JavaScript, which had always appeared.
Anyway, I only want my app working again, no matter how.
Any help will be profoundly appreciated!
You need to know differences between compilation error and runtime error. It seems that what you've experiencing is a runtime error. Please check out the JavaScript file being executed by Node.js.
Currently Node.js does not yet support ES6 module syntax, you need to have your module field in tsconfig.json to be commonjs. Ideally in your output JavaScript file, import mongodb = require('mongodb'); should be emitted as const mongodb = require('mongodb'); when targeting ES6 or var mongodb = require('mongodb'); when targeting ES5.

How to use AMD code completion with webstorm and requirejs?

I have something like this
define(function(require) {
var Router = require('./router');
var Backbone = require('backbone');
var Log = require('log');
...
Apparently Webstorm is meant to support AMD modules but I can't get it to work, instead a get a massive list of properties from every .js file in the project.
Has anyone had any luck getting Webstorm code completion / refactoring with requirejs modules?
Update, I was able to get it working if I following the following construct
define(['backbone', './router', './log'], function(Backbone, Router, Log) {
however, all paths have to be relative. This is impractical for a path that is configured in require.config, so Backbone does not have code completion.
requirejs.config({
baseUrl: 'js',
paths: {
'backbone' : '../bower_components/backbone/backbone-min',
...
Plus, the above syntax becomes ugly when there are many dependencies...
update 2
The above does not work if you change directory, for example, the Log below does not get code completion:
define(['backbone', './router', '../utils/log'], function(Backbone, Router, Log) {
As commented above, the support for AMD and CustomJS modules is on the roadmap for WebStorm 8. The Early Access Program started recently offers a preview for the AngularJS and Spy-js support only, but the AMD support is in progress and I hope that it'd appear in the next update.
In the meanwhile, you can try the Require.js plugin which provides a partial support for the requirejs modules. You'll get path completion for the module dependencies in the define call, including the requirejs plugins recognition:
The code completion offers so many "false positives" that you'd better learn the interface of your objects and use the "IntelliSense" just as a hint or a help to finish long identifiers; I doubt that the plugin helps the IDE here:
Other features like finding usages or refactoring (rename file and rename object) do not work across the boundary of the module closure. You're better off with the Replace in Path feature...
Notes to the plugin: The path to the config file in the plugin settings is relative to the public directory (the base URL). Also, I'd recommend checking out the binary package from the github project site, which may offer a newer version than the WebStorm plugin manager. (The 0.13 downloaded from there fixed crashing of the plugin with my project, while the WebStorm IDE still offered the 0.12.)
UPDATE: The issue WEB-825 appears to be partially fixed in WebStorm-134.1081 downloadable from EAP. The Find Usages feature recognizes formal parameters initialized from the requirejs dependencies and searches for the module references in the project instead of for the variable reference in the current closure:
Refactoring has improved. Renaming a file in the projtect does affect all module references, but it introduces a relative path to the requirejs base directory (URL). For example, renaming toolitems.js in the src/model directory to menuitems.js changes all references from "model/toolitems" to "../model/menuitems"; providing the requirejs base directory is in the src directory. Renaming a method works in the entire project. Renaming an object works only within the scope of the current closure. Should work globally? You may intentionally choose different object names for the same module export in every closure with Require.js... Still, it is a good habit to use the same names for consistency and an improvement here would be nice.
The Require.js plugin, which brings a partial AMD support to WebStorm 7 seems not to be needed in WebStorm 8 anymore.
UPDATE II: The Require.js plugin still helps the WebStorm 8 users. It recognizes baseUrl and paths from the Require.js configuretion. You can map module path prefixes to different directory roots and still have to "Go To Location" feature working:
// file configured for the Require.js config file path
require.config({
paths: {
core: '../core/src',
recman: '../recman/src',
app: '.'
}
});
// Example of a module from the app project
define([
'core/model/node', 'recman/model/hold, 'app/view/manager'
], function (NodeModel, HoldModel, ManagerView) {
...
});

Resources