L5-swagger api documentation: Getting error Required #OA\PathItem() not found - openapi

After reading these 2 posts here on Stackoverflow:
How to Solved ErrorException : Required #OA\PathItem() not found
Can't generate API documentation in l5-swagger
I still get an error Required #OA\PathItem() not found after running php artisan l5-swagger:generate.
This is my Controller.php part:
/**
* #OA\Info(
* title="My First API Documentation",
* version="0.1",
* #OA\Contact(
* email="info#yeagger.com"
* ),
* ),
* #OA\Server(
* description="Learning env",
* url="https://foo.localhost:8000/api/"
* ),
*/
class Controller extends BaseController
{
and this is my ProfileController part:
/**
* #OA\Get(
* path="/profiles",
* #OA\Response(
* response=200,
* description="Successful operation",
* ),
* #OA\PathItem (
* ),
* )
*/
function index()
{
return new ProfileCollection(Profile::with('user')->paginate());
}
What am I overlooking here?
If anyone can explain and help that would be great :)
EDIT - SOLUTION
The problem occured because I am using a laravel modules package and I had to change a bit of code in the l5-swagger.php config file:
'annotations' => [
base_path('Modules/Api/Http'), <-- changed the base path to the correct module
],
I then copied the main Controller.php from App/Http/Controllers to the same Module to also get rid of the occuring #OA\Info() not found error after that.

When I first installed and configured I was having the same error. Turns out that just #OA\Info is not enough to generate the document. In addition to that, it requires atleast one path entry. After adding an api endpoint annotation it got fixed.
example:
/**
* #OA\Get(
* path="/api/users",
* #OA\Response(response="200", description="An example endpoint")
* )
*/
public function getUsers() {
...
}

As per migration documentation you need to import Annotations class use OpenApi\Annotations as OA; that will fix your problem.

/**
* Remove the specified resource from storage.
*
* #return \Illuminate\Http\JsonResponse
*/
if there are these codes above my index() function, it should be deleted immediately. that's why I got this error

Related

How does one make jsdoc actually output docs?

I'm trying to get jsdoc (version 3.6.7, using node 16) to turn my documented js code into actual documentation, but no matter what I do it just generates an out directory with an index.html that is primarily empty lines, rather than documentation. I've asked about this over on the issue tracker (after I searched the docs and the web for information on what one might be doing wrong to get jsdoc to generate empty files, but I can't for the life of me find anything useful that addresses that) but since it's been a few days, it feels useful to ask here as well, so that an answer in either place can be cross posted.
Running the jsdoc command does not flag any errors with the input, and completes with a normal zero exit code but generates nothing useful, so hopefully someone here's run into his before and can explain what is necessary in addition to the follow code to actually get jsdoc to generate docs.
An example of code that has no errors according to jsdoc, but also yields no docs whatsoever:
import { Errors } from "../errors.js";
import { Models } from "./models.js";
/**
* Several paragraphs of text that explain this class
*
* #class
* #namespace model
*/
export class Model {
/**
* #ignore
*/
static ALLOW_INCOMPLETE = Symbol();
/**
* Also several paragraphs explaining the use of this function.
*
* #static
* #param {*} data
* #param {*} allowIncomplete (must be Model.ALLOW_INCOMPLETE to do anything)
* #returns {*} a model instance
* #throws {*} one of several errors
*/
static create = function (data = undefined, allowIncomplete) {
return Models.create(
this,
data,
allowIncomplete === Model.ALLOW_INCOMPLETE
);
};
/**
* code comment that explains that if you're reading
* this source, you should not be using the constructor,
* but should use the .create factory function instead.
*
* #ignore
*/
constructor(caller, when) {
if (!caller || typeof when !== "number") {
const { name } = this.__proto__.constructor;
throw Errors.DO_NOT_USE_MODEL_CONSTRUCTOR(name);
}
}
}
Running this with jsdoc test.js yields an out dir with an index.html and test.js.html file, the first containing some thirty newlines of "no docs here" with boilerplate wrapper HTML code, and the second containing the original source code with nothing else useful either.
What else does one need to do to get jsdoc to actually generate documentation here?
I have fixed it by not using export infront of classes, instead exporting them at the end of the file. like this:
import { Errors } from "../errors.js";
import { Models } from "./models.js";
/**
* Several paragraphs of text that explain this class
*
* #class
* #namespace model
*/
class Model {
/**
* #ignore
*/
static ALLOW_INCOMPLETE = Symbol();
/**
* Also several paragraphs explaining the use of this function.
*
* #static
* #param {*} data
* #param {*} allowIncomplete (must be Model.ALLOW_INCOMPLETE to do anything)
* #returns {*} a model instance
* #throws {*} one of several errors
*/
static create = function (data = undefined, allowIncomplete) {
return Models.create(
this,
data,
allowIncomplete === Model.ALLOW_INCOMPLETE
);
};
/**
* code comment that explains that if you're reading
* this source, you should not be using the constructor,
* but should use the .create factory function instead.
*
* #ignore
*/
constructor(caller, when) {
if (!caller || typeof when !== "number") {
const { name } = this.__proto__.constructor;
throw Errors.DO_NOT_USE_MODEL_CONSTRUCTOR(name);
}
}
}
export {Model}
Turns out this was posted too early: taking the time to start at the official documentation for classes over on https://jsdoc.app/tags-class.html and running that example through jsdoc works perfectly fine, and subsequently building out that example to match the actual file's code yields working documentation just fine, too.
And in this specific case, there were several problems:
adding #namespace paired with #class was the main problem. Neither were necessary, but the #namespace entry changes how jsdoc parses the rest of a file's documentation, where if methods are to show up, they must use a #name property that includes that namespace. As that was not the case here, nothing ended up showing in the documentation.
having an #ignore on the constructor function, rather than using the #hideconstructor property on the class meant that even with #namespace removed, no documentation got written. JSdoc treats the class docs heading and the constructor as the same thing, so #ignoreing the constructor is treated the same as ignoring the entire class.
Fixing both mistakes, and removing the unnecessary #class at the top, gives perfectly fine documentation:
import { Errors } from "../errors.js";
import { Models } from "./models.js";
/**
* Several paragraphs of text that explain this class
*
* #hideconstructor
*/
export class Model {
/**
* #ignore
*/
static ALLOW_INCOMPLETE = Symbol();
/**
* Also several paragraphs explaining the use of this function.
*
* #static
* #param {*} data
* #param {*} allowIncomplete (must be Model.ALLOW_INCOMPLETE to do anything)
* #returns {*} a model instance
* #throws {*} one of several errors
*/
static create = function (data = undefined, allowIncomplete) {
return Models.create(
this,
data,
allowIncomplete === Model.ALLOW_INCOMPLETE
);
};
/**
* code comment that explains that if you're reading
* this source, you should not be using the constructor,
* but should use the .create factory function instead.
*/
constructor(caller, when) {
if (!caller || typeof when !== "number") {
const { name } = this.__proto__.constructor;
throw Errors.DO_NOT_USE_MODEL_CONSTRUCTOR(name);
}
}
}

Documenting inner method of function expression with jsDoc 3.6.6 - Intellisense works but jsdoc doesn't

I want to document a function expression from some example Alexa SDK code.
This person seems to know what they're doing, except the jsdoc linter doesn't like the inline import like this:
#param {import('ask-sdk-core').HandlerInput} handlerInput
so I just used the standard require at top of file workaround.
const { HandlerInput } = require('ask-sdk-core')
and then inline:
#param {HandlerInput} handlerInput - blah
Intellisense loves it, everything seems great...
except JSDOC gives me nothing:
I seem to have all other aspects of jsdoc working perfectly and everything documents beautifully.
Except this.
I have tried referencing the constant as almost every type, scoured github, read things link the following:
JSDoc not recognizing exported function
JSDOC: How to document inner variables of function
Here's a slimmed down abridged version of the example code I linked to above. What have I missed or got wrong? Any ideas appreciated. Thanks.
const { HandlerInput } = require('ask-sdk-core')
/** #constant */
const audioController = {
/**
* Handles the creation of a response with an AudioPlayerPlayDirective, relying on previously set playbackInfo values. Also updates certain appSettings to maintain correct state of the skill.
*
* #param {HandlerInput} handlerInput - defined by Alexa
* #returns {Promise<HandlerInput.Response>} alexa response object
*/
async play (handlerInput) {
const speakOutput = 'playing'
return handlerInput.responseBuilder.speak(speakOutput).getResponse()
},
/**
* Handles the creation of a response with an AudioPlayerStopDirective
*
* #param {HandlerInput} handlerInput - defined by Alexa
* #returns {object} alexa response object
*/
stop (handlerInput) {
const speakOutput = 'stopping'
return handlerInput.responseBuilder.speak(speakOutput).getResponse()
}
}
module.exports = { audioController }
Thanks to #customcommander for the guidance, I was then able to find this Q&A which pointed me towards the following solution. Unfortunately, VSCode intellisense doesn't "see" namespace definitions in separate files, although jsdoc has no problem.
It seems like jsdoc doesn't require #memberof, but from what I can find it's good practice(?) and does no harm. Many thanks for the help.
/**
* Audiocontroller namespace
*
* #namespace audioController
*/
const audioController = {
/**
* Handles the creation of a response with an AudioPlayerPlayDirective
*
* #param {HandlerInput} handlerInput - defined by Alexa
* #memberof audioController
* #returns {object} alexa response object
*/
async play (handlerInput) {
const speakOutput = 'playing'
return handlerInput.responseBuilder.speak(speakOutput).getResponse()
},
/**
* Handles the creation of a response with an AudioPlayerStopDirective
*
* #param {HandlerInput} handlerInput - defined by Alexa
* #memberof audioController
* #returns {object} alexa response object
*/
stop (handlerInput) {
const speakOutput = 'stopping'
return handlerInput.responseBuilder.speak(speakOutput).getResponse()
}
}
module.exports = { audioController }

JSDoc Class suggested layout

I'm brand new to JSDoc, and I'm trying to figure out the best way to tag my code. For some reason after I label something as a #class, I can't get anything to appear as #inner:
/**
* The logger, to simply output logs to the console (or potentially a variable)
* #class Logger
* #requires 'config/globalConfig'
*/
define(["config/globalConfig"], function (config) {
/**
* Instantiate a new copy of the logger for a class/object
* #constructor
* #param name {string} - The name of the class instantiating the logger
*/
return function (name) {
/**
* #memberOf Logger
* #type {string}
*/
this.name = name;
/**
* Place the message on the console, only for "DEV" level debugging
* #function
* #memberOf Logger
* #param message {string}
*/
this.debug = function (message) {
... some code ...
};
};
});
Right now all the members are appearing as <static>. If I add the #inner tag to any of the attributes/functions they vanish completely from the output.
Edit: I also forgot to mention. The #constructor flag doesn't seem to be working either. If I remove that entire section, it appears the same in the output. The output does not include the #param that I would like to mention with my constructor.
Please let me know if this is completely off, I'm just kind of guessing here since the JSDoc3 documentation is a bit difficult to read.
So I figured it out, still not sure if it's absolutely correct. I had to use "Logger~name" to have it appear correctly as an inner function. According to the JSDoc documentation, this ~ is "rarely used". Seems to be the only thing that works for me.
define(["config/globalConfig"], function (config) {
/**
* The logger, to simply output logs to the console (or potentially a variable)
* #class Logger
* #param name {string} - The name of the class instantiating the logger
*/
return function (name) {
this.name = name;
/**
* Place the message on the console, only for "DEV" level debugging
* #function Logger~debug
* #param message {string}
*/
this.debug = function (message) {
... code ...
};
};
});

How to Document following function in JSDoc JS-Toolkit

*How to Document following function in JSDoc JS-Toolkit *
I want to document try and help method in this main function
but i did not figure it out how to do that.
/** Sample doc
* #class
* #constructor
* #name Sample
*/
var main=function(){
this.value="";
/** help function
* #param {String} Name
*/
this.help=function(name){
console.log('help me'+name);
}
/** help function
* #param {String} Name
*/
this.try=function(name){
console.log('try me'+name);
}
}
I just struggled with this for several hours. I tried:
#member
#augments
#method
#this
From the examples and tutorials I found, member functions and variables should appear in the output simply by having /** description/* comments above them, but I found that was not the case. Like you, I'm using standard JavaScript constructors, where this should be able to be inferred automatically due to the #constructor being in place. Maybe there's some wrinkle I'm not seeing.
In the end, I found two tags that worked for me, #name and#memberof. They both allow you to specify the object that the property is a member of. Using #name in this way is undocumented (at least, I didn't see it anywhere), but very straightforward. You'll also need to use #function.
Here's an example with the #name tag:
/** help function
* #name Sample.try
* #function
* #param {String} Name
*/
this.try=function(name){
console.log('try me'+name);
};
And here's an example with the #memberof tag:
/** help function
* #memberof Sample
* #function
* #param {String} Name
*/
this.try=function(name){
console.log('try me'+name);
};
As you can see the output is almost the same. The only difference that I see is that #memberof includes this. in the method name. For that reason I've settled on using #name.
The remaining issue is that the functions are per-instance, not <static>.
Hope this helps!

Troubleshooting "[Syntax Error] Expected PlainValue, got ')'"

I am getting this error in my annotations docblock for Doctrine 2:
Doctrine\Common\Annotations\AnnotationException: [Syntax Error] Expected PlainValue, got ')'
After looking for an answer I found this reference Stackoverflow Question 3500125 which in essence says to put quotes around all values in annotations.
With the annotation block I have this does not seem possible. here is my example that is throwing the error.
/**
* #var tags
*
* #ManyToMany(targetEntity="namespace\to\tag")
* #JoinTable(name="content_tag",
* joinColumns={
* #JoinColumn(name="content_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #JoinColumn(name="tag_id", referencedColumnName="id")
* }
* ) // This is the line indicated by the error
*/
private $tags;
If I follow the advice of the answer I found in stack overflow which is to quote out the values, my code will be like this:
/**
* #var tags
*
* #ManyToMany(targetEntity="namespace\to\tag")
* #JoinTable(name="content_tag",
* joinColumns="{
* #JoinColumn(name="content_id", referencedColumnName="id")
* }",
* inverseJoinColumns="{
* #JoinColumn(name="tag_id", referencedColumnName="id")
* }" // Note the extra quotation marks
* )
*/
private $tags;
Which is not right at all.
For people who have come here but not because of doctrine, my mistake was using single quotes instead of double quotes in the #Routes annotation.
WRONG:
/**
* #Route('/home')
*/
RIGHT
/**
* #Route("/home")
*/
It was a silly mistake, the error string was not very helpful as it pointed to the line i showed in my question as the line that the error was on. The fact was that this entity was extending a parent object, the parent had the #Entity tag but the child did not, i moved it and everything works fine.
I Just had the same kind of error by using an assert for an entity :
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* mode = 'strict',
* normalizer = 'trim'
* )
Turning it into
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* mode = "strict",
* normalizer = "trim"
* )
Fixed it :)