How to use JSDoc with destructured imports? - node.js

I am using VSCode as my NodeJS editor and the Preview JSDOC extension.
I wonder how I can use JSDoc with restructured imports. See the example below.
I created a module, Module A:
/**
* Some function description
* #return a string + 1234
*/
const myFuncA = (someParams) => {
return `${someParams} 1234` // or whatever
};
/**
* This is a string.
*/
const myPropB = "A string";
// ...
module.exports = {
myFuncA,
myPropB
}
In module B, I'd like to use some properties or functions from module A:
Module B:
const { myFuncA } = require('../moduleA');
const propA = myFuncA(4321);
However, when hovering over myFuncA (or when typing myFuncA(...), the description is not shown.
I'm new to JSDoc, however, their docs don't cover my specific case.

I was searching for answer for this as well, and I think the best thing for this solution is to use the #memberof module:<your-module-name> syntax.
So in Module B at the top you would add something like this
/** module MyModuleName */
const { myFuncA } = require('../moduleA');
Then in Module A you would add the #memberof module:<module-name> decorator.
/**
* Some function description
* #return a string + 1234
* #memberof module:MyModuleName
*/
const myFuncA = (someParams) => {
return `${someParams} 1234` // or whatever
};
Extra Information:
As I was looking for a solution to this problem, I had the assumption that JSDoc would resolve imports. JSDoc does not resolve imports, which makes a lot of sense. If you want a function to belong to another module, you have to let JSDocs know. Credit to this github issue thread which helped me settle on this answer.

Related

How to initialise class in the require statement? (typescript)

How does a basic class export need to look like so when required, it can be initialised like this:
const api = require('myapi')('key_...');
If I understand your question, you're wanting to the myapi module to instantiate a class (ie BasicClass) and return this via a function that is the default export. One way to achieve that in TypeScript is via the following:
/* The myapi module */
/* The "basic class" that will be instantiated when default export function is called */
class BasicClass {
constructor(key:string) {
console.log(`Constructor got key: ${key}`)
}
}
/* The default module export is a function that accepts a key string argument */
module.exports = (key:string) => {
/* The function returns an instance of BasicClass */
return new BasicClass(key)
}
The myapi module could then be used as follows:
const api = require('myapi')('key_...');
/* api is instance of BasicClass */
Hope that helps

merging two or more node.js require modules into one namespace

Google Flatbuffers creates in (AMD?) module for each table that one wants. I have them all in one name space called PNTCI.
Right now, I am doing something ugly and non-intuitve to merge the name spaces together by doing successive includes to the PNTCI namespace like this:
const telem = require('../messages/Telemetry_generated').PNTCI
const PNTCI = Object.assign(telem, require('../messages/header_generated').PNTCI)
The again the reason is that the autogenerated require modules have a old fashioned format that looks like this for the Header_generated.js :
// automatically generated by the FlatBuffers compiler, do not modify
/**
* #const
* #namespace
*/
var PNTCI = PNTCI || {};
/**
* Common header for all PNTCI message payloads
*
* #constructor
*/
and the end of the file looks like this:
/**
* #param {flatbuffers.Builder} builder
* #param {flatbuffers.Offset} offset
*/
PNTCI.Header.finishHeaderBuffer = function(builder, offset) {
builder.finish(offset);
};
// Exports for Node.js and RequireJS
this.PNTCI = PNTCI;
and for Telemetry_generated.js
// automatically generated by the FlatBuffers compiler, do not modify
/**
* #const
* #namespace
*/
var PNTCI = PNTCI || {};
/**
* #constructor
*/
PNTCI.PosVector = function() {
/**
* #type {flatbuffers.ByteBuffer}
*/
this.bb = null;
and then the end of the file looks like this:
PNTCI.Telemetry.finishTelemetryBuffer = function(builder, offset) {
builder.finish(offset);
};
// Exports for Node.js and RequireJS
this.PNTCI = PNTCI;
The use of namespaces isn't idiomatic to Node.js because a module itself acts as a namespace, so the problem is specific to these particular modules.
It can be written shorter with object spread syntax:
const PNTCI = {
...require('../messages/Telemetry_generated').PNTCI,
...require('../messages/header_generated').PNTCI
};
Which is syntactic sugar for:
const PNTCI = Object.assign({},
require('../messages/Telemetry_generated').PNTCI,
require('../messages/header_generated').PNTCI
);
If these modules are constantly used together, it may be beneficial to re-export them as single module:
module.exports = {
...require('../messages/Telemetry_generated').PNTCI,
...require('../messages/header_generated').PNTCI
};
Since there's generally no need for namespaces in Node, merging modules under single PNTCI variable may be unneeded; modules could be imported separately to different variables. This makes the application more modular if only some of these modules are used in some places.

Is this a good way to use module.exports?

I'm curious if the following way is a good approach to use the module.exports functionality.
And if so, what is the best way to add commentary to the code so JSDoc3 can handle it correctly.
I'm currently exporting functions as follows:
Let say we have a module1.js with the following code:
/**
* Module1 module
* #module Module1
*/
module.exports = {
// no jsdoc commentary on purpose
function1: function(param1) {
function1(param1);
},
/**
* Function2
*
* Function that will do something
* #returns {boolean} return value
*/
function2: function() {
return function2();
},
}
/**
* Function1
*
* Function that will do something
* #param param1 {string} First parameter
*/
function function1(param1){
console.log(param1);
// do something
}
/**
* Function2
*
* Function that will do something
* #returns {boolean} return value
*/
function function2() {
// do something
return true;
}
and in module2.js
/**
* Module2 module
* #module Module2
*/
// Requirements
module1 = require('./module1.js');
/**
* myFunction
*
* Function that will do something
*/
function myFunction() {
const param1 = "Parameter1";
module1.function1(param1); // call function1 from module 1
}
// just an example of function2 in module2.js
const myBoolean = module1.function2();
// more stuf
The problem with this approach is that function1 will now only be described in the jsdoc file as 'inner'(local) function, and function2will now be duplicated in the generated jsdoc file one as 'static' (the exported) and one as 'inner' (local) function.
Why this approach:
The reason for this approach is: I want no functionality in exported functions. I want other developers to easily see what functions are exported. So the real functionality is put in the local function below the exports.
The question:
Is this a correct way to use the module exports?
And is this a correct way to commentary the code? (for JSDoc3)
ps: im pretty new with NodeJS

Working example of event tag in jsdoc3

Can someone please give me an example on how to use the #event tag properly.
I've looked at the jsdoc3 documentation here:
http://usejsdoc.org/tags-event.html
but I could not get it working.
I am using nodejs, and I have a module in MyClass/index.js which exports a constructor by the name of MyClass:
module.exports = MyClass;
myClass = function () { ... };
and I have tried to add
/**
* Snowball event.
* #event MyClass#snowball
*/
In the compiled docs, snowball appears in the global list of events, but when I click on it, it tells me
The requested URL /{path-to-my-docs}/MyClass.html was not found on this server.
Thanks in advance.
This works fine:
/**
* #class
*/
function Blah() {
}
/**
* #event Blah#something
* #type {Object}
* #property {integer} some_field Represents something or other.
*/

JsDoc + Backbone + CommonJS + WebStorm. Cannot resolve references to Class Constructor from facade

How can one force JsDoc to consider a parameter as a reference to a Class Constructor?
Hi! I am struggling to make JsDoc for my library, but there must be something I am missing here. I documented part of my library (in this example, the "Relation" class). The facade for the library is the "Rajs" class. It contains a parameter containing a reference to the Reference class. I would like to be able, when I require "Rajs" in another file, to be able to access the jsDoc documentation. But it just doesn't recognize this.
I am using WebStorm.
In this file, I define a Class named "Relation"
relation.js - The "documented" class
// File relation.js
//-----------------
var Backbone = require('backbone');
var Relation = Backbone.Model.extend(
/** #lends Relation.prototype*/
{
/**
* #class Relation
* #augments Backbone.Model
* #constructor
*/
initialize : function(){
// Initialization ...
}
});
module.exports = Relation;
Here, this is the facade for my library. Everything should be accessed through "Rajs", preventing the user to have to require every part of my library. Rajs will require everything and the user will simply have to require Rajs.
rajs.js -- the Facade
// File rajs.js
//--------------
var Backbone = require('backbone');
var Relation = require('./relation');
var Rajs = Backbone.Model.extend( /** #lends Rajs.prototype */
{
/**
* #class Rajs
* #augments Backbone.Model
* #constructor
*/
initialize : function(){
// Initialization ...
this.Relation = Relation;
}
});
Module.exports = Rajs;
This would be the end-user. He would require('rajs') and should have access to the whole library without having to require('rajs-x'), ('rajs-y'), ('rajs-z')... It actually works, but I'd like to provide the user JsDoc for autocompletion.
Here, in app.js, the user required core but could not access the jsDoc for Relation.js. Why is that so?
app.js -- The end-user file
// File app.js
//------------
var Rajs = require('./rajs');
var rajs = new Rajs();
var relation = new rajs.Relation(); //Here, jsDoc does not recognize core.Relation as being of class Relation. Instead, it sees it like a property if Rajs
![Does not recognize Relation.js methods and properties][1]
Thank you for your help!

Resources