JSDoc reference function in object literal (CommonJS module.exports) - jsdoc

I'm writing a CommonJS module and have all of my methods defined as function definitions within the module. Those methods are then defined in the module.exports object. This is all written with es6 as well.
However, with my annotations, the generated documentation only links to the object definition and does not display the actual documentation for the methods.
// file named utils.js
const regular = require('regular');
const isEmpty = require('lodash.isempty);
/**
* #memberof utils
* #param {object} obj The value to check if it is an object or not
* #returns {boolean}
*/
function isTrueObject(obj) {
return !Array.isArray(obj) && typeof obj === 'object' && !isEmpty(obj) ;
}
/**
* #memberof utils
* #param {*} val
* #returns {boolean}
*/
function isNumberLike(val) {
return isNumber(val) || regular.number.test(val);
}
/**
* #module utils
*/
module.exports = {
isTrueObject,
isNumberLike
};
If i keep the module.exports property names as-is, no docs get generated, except for a blank page for utils:
I have to do the following to get the proper documentation:
// file named utils.js
const regular = require('regular');
const isEmpty = require('lodash.isempty);
/**
* #memberof utils
* #param {object} obj The value to check if it is an object or not
* #returns {boolean}
*/
function isTrueObject(obj) {
return !Array.isArray(obj) && typeof obj === 'object' && !isEmpty(obj) ;
}
/**
* #memberof utils
* #param {*} val
* #returns {boolean}
*/
function isNumberLike(val) {
return isNumber(val) || regular.number.test(val);
}
/**
* #module utils
*/
module.exports = {
/**
* #function
* #param {object} obj The value to check if it is an object or not
* #returns {boolean}
*/
isTrueObject,
/**
* #function
* #param {*} val
* #returns {boolean}
*/
isNumberLike
};
This clearly is not ideal since the documentation is not right next above the actual function declaration and this easily leads to duplication of documentation. Is there a different way to link these and generate the same documentation?
I tried the following but all i got were links to the code itself and no actual documentation output:
/**
* #module utils
*/
module.exports = {
/** #see module:utils#isTrueObject */
isTrueObject,
/** #borrows isNumberLike as isNumberLike */
isNumberLike
};
using either #see or #borrow generates the following:
This obviously is not the desired output.
Does anyone know how to properly document this without needless duplication?

Move the #module declaration at the top of the file and replace #memberof utils with #static produces the intended result:
// file named utils.js
/**
* #module utils
*/
const regular = require('regular');
const isEmpty = require('lodash.isempty);
/**
* #static
* #param {object} obj The value to check if it is an object or not
* #returns {boolean}
*/
function isTrueObject(obj) {
return !Array.isArray(obj) && typeof obj === 'object' && !isEmpty(obj) ;
}
/**
* #static
* #param {*} val
* #returns {boolean}
*/
function isNumberLike(val) {
return isNumber(val) || regular.number.test(val);
}
module.exports = {
isTrueObject,
isNumberLike
};

Related

`Rest parameters JSDOC` is not correctly flagged in vscode

Is there something wrong with my code that caused vscode to have no correct tip?
/**
*
* #param {...Object} elementList
* #param {string} elementList[].type
*/
function add(...elementList) {
// vscode tip: elementList is (parameter) elementList: any[]
// expect: elementList is {type: string;}[]
elementList.map(e => e)
}
// use
add({ type: 'div' }, { type: 'h1' })
You want the format #param {type} parameterName, e.g.
/**
* #param {{type: string}[]} elementList
*/
function add(...elementList) {
elementList.map(e => e)
// ^^^^^^^^^^^ (parameter) elementList: {type: string}[]
}
Alternatively, you can create re-usable type definitions with JSDoc:
// Define an Object type named MyElement with one property (type) of type string.
/**
* #typedef {Object} MyElement
* #property {string} type
*/
/**
* #param {MyElement[]} elementList
*/
function add(...elementList) {
elementList.map(e => e)
// ^^^^^^^^^^^ (parameter) elementList: MyElement[]
}

jsdoc typedef global to local, why not overridden?

Props with global type declaration
I want to overwrite it with the local type.
Below is the code and comments.
/* global */
/**
* #typedef {{key: string, value: string}} Props
*/
/**
* #type {Props}
*/
let globalTypeObj = {};
/* local */
class LocalType {
/**
* #typedef {{name: string, age: number}} Props
* #param {Props} props
*/
constructor(props) {} // <- Why doesn't LocalType Props apply here?
}
/**
* #namespace {LocalType} // I used namespace LocalType.
* #type {Props}
*/
let LocalTypeObj = {}; // <- Why doesn't LocalType Props apply here?
Please teach me.

How to comment a method returning a copy of this, using JSDoc?

How to describe, using the JSDoc tags, this derivate() return value? I'm looking for a syntax to describe (#returns) the object creation, resulting from mixin of the current object AND the provided properties, to improve the autocompletion.
I thought to something like #returns #mixes (this, properties) but it isn't a valid syntax, apparently.
const obj = {
/**
* #param {{
* ...properties: *
* }} [properties]
* #returns {{}}
*/
derivate ({ ...properties } = {}) {
return { ...this, ...properties }
}
}
Just found a solution (but tsc doesn't like it, then still open for a better soltion):
/**
* #typedef Obj
* #type {Object}
*/
/**
* #typedef Properties
* #type {Object}
*/
/**
* #typedef Return
* #type {Object}
* #augments Obj
* #augments Properties
*/
/**
* #type {Obj} obj
*/
const obj = {
/**
* #param {Properties} [properties]
* #returns {Return}
*/
derivate ({ ...properties } = {}) {
return { ...this, ...properties }
}
}

How can i access a temporarily argument (password-reenter) in a Validator with PHP in TYPO3 without make an extra sql-field?

TYPO3-Version: 8.7.7
I want to access $this->request->getArguments() in a Validator for TYPO3 in PHP.
I set a temporary field in fluid with:
<label for="reenter_password" class="reenter_password{rm:hasError(property:'reenter_password',then:' text-danger')}">
Reenter Password*
</label><br>
<f:form.password name="reenter_password" id="reenter_password"/>
If i set property instead of name in <f:form.password name="reenter_password" id="reenter_password"/> i get the following Error:
#1297759968: Exception while property mapping at property path "": Property "reenter_password" was not found in target object of type "RM\RmRegistration\Domain\Model\User".
I don't want to set a Model-Property, because this property should only use for checking with the passwortfield for equality and shouldn't get a TCA or SQL-Table for Storage.
Here is my Action, where i call the Validators:
/**
* Complete New User Registeration
*
* #param User $newRegisteredUser
* #validate $newRegisteredUser \RM\RmRegistration\Validation\Validator\NewRegisteredUser
* #validate $newRegisteredUser \RM\RmRegistration\Validation\Validator\CompleteProfileUser
*/
public function completeNewRegisteredUserAction(User $newRegisteredUser)
{
// Store Changes, Update and Persist
$newRegisteredUser->setPassword($this->saltThisPassword($newRegisteredUser->getPassword()));
$this->userRepository->update($newRegisteredUser);
$this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager')->persistAll();
}
In the Validator i can get to the Password-Field with:
\TYPO3\CMS\Core\Utility\GeneralUtility::_POST()['tx_rmregistration_registration']['reenter_password']
But is it possible to get the Value temporary to the UserModel to check it in the Validator like this:
// Compare Entered Passwords
if ($user->getPassword() == $user->getReenteredPassword()) {
return TRUE;
} else {
return FALSE;
}
Make an own (view) model for the password verification process or give the $newRegisteredUser a (transient or not) property for the reenterd password. Then use an own validator (see here).
class UserValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator {
/**
* Object Manager
*
* #var \TYPO3\CMS\Extbase\Object\ObjectManager
* #inject
*/
protected $objectManager;
/**
* Is valid
*
* #param mixed $user
* #return boolean
*/
public function isValid($user) {
if ($user->getPassword() !== $user->getPasswordConfirmation()) {
$error = $this->objectManager->get(
'TYPO3\CMS\Extbase\Validation\Error',
'Password and password confirmation do not match.', time());
$this->result->forProperty('passwordConfirmation')->addError($error);
return FALSE;
}
return TRUE;
}
}
And use in controller like this:
/**
* action create
*
* #param \Vendor\Ext\Domain\Model\User $user
* #validate $user \Vendor\Ext\Domain\Validator\UserValidator
*
* #return void
*/
public function createAction(\Vendor\Ext\Domain\Model\User $user) {
}

JSDoc - How to assign a function as a property of another function

Given the following, when I run jsdoc, the output does not show anything for the foo.bar property.
/**
* Foo
*/
const foo = function foo() {
//...
}
/**
* Bar
*/
foo.bar = function bar() {
//...
}
How can I display bar as being a property on foo?
There are a lot of possibilities to achieve this. The following are just a couple of them ...
Use #memberof which is the tag identifies a member symbol that belongs to a parent symbol.
/**
* Foo
*/
const foo = function foo() {
//...
}
/**
* Bar
* #memberof Foo
*/
foo.bar = function bar() {
//...
}
Use #prop which is the tag to easily document a list of static properties of a class, namespace or other object.
/**
* Foo
* #namespace
* #property {object} bar - is this "bar" property?
*/
const foo = function foo() {
//...
}
/**
* Bar
*/
foo.bar = function bar() {
//...
}
You may use #alias as well, it's all depend on what is your Foo and Bar; Are they objects, namespace, functions, properties, etc. I would suggest to read a bit on JSDoc documentation to get to know all the possibilities.
here is a #typedef solution, with property comments
// types.js
/**
* #typedef {(s: string) => number} _SomeFunction
* convert string to number
*
* #typedef {Object} SomeProps
* #property {number} someProp1 some property 1
* #property {string} someProp2 some property 2
* #property {(s: string) => number} someProp3
* some property 3
*
* #typedef {_SomeFunction & SomeProps} SomeFunction
*/
/** #typedef {import("./types.js").SomeFunction} SomeFunction */
/** #type {SomeFunction} */
var f = s => s.length
f.someProp1 = 1
f.someProp2 = ""
f.someProp3 = s => (2 * s.length)