Document destructured function parameter in JSDoc - arguments

Previously I've always documented my object parameters as follows:
/**
* Description of the function
*
* #param {Object} config - The configuration
* #param {String} config.foo
* #param {Boolean} [config.bar] - Optional value
* #return {String}
*/
function doSomething (config = {}) {
const { foo, bar } = config;
console.log(foo, bar);
// do something
}
But I am unsure what the best approach is with desctructured function parameter. Do I just ignore the object, define it somehow or what is the best way of documenting it?
/**
* Description of the function
*
* #param {String} foo
* #param {Boolean} [bar] - Optional value
* #return {String}
*/
function doSomething ({ foo, bar } = {}) {
console.log(foo, bar);
// do something
}
I feel like my approach above doesn't make it obvious that the function expects an object and not two different parameter.
Another way I could think of would be using #typedef, but that might end up being a huge mess (especially in a larger file with many methods)?
/**
* #typedef {Object} doSomethingConfiguration
* #property {String} foo
* #property {Boolean} [bar] - Optional value
*/
/**
* Description of the function
*
* #param {doSomethingConfiguration}
* #return {String}
*/
function doSomething ({ foo, bar } = {}) {
console.log(foo, bar);
// do something
}

This is how it's intended, as described in the documentation.
/**
* My cool function.
*
* #param {Object} obj - An object.
* #param {string} obj.prop1 - Property 1.
* #param {string} obj.prop2 - Property 2.
*/
const fn = function ({prop1, prop2}) {
// Do something with prop1 and prop2
}
So, your first example is pretty much correct.
Another example with some deeper nesting:
/**
* Nesting example.
*
* #param {object} param
* #param {number} param.a - First value
* #param {object} param.b - Wrapper
* #param {number} param.b.c - Second value
* #return {number} sum a and b
*/
const letters = ({a, b: {c}}) => a + c;

I personally use this one:
/**
* #param {{
a: number
b: number
}} param0
* #returns {number} The sum
*/
const func = ({ a, b }) => a + b;
Just create the object right there.
I also take advantage of TypeScript, and would declare obtional b as b? or b: number | undefined as JSDoc also allows unions

See JSDoc's "Documenting a parameter's properties":
/**
* Assign the project to an employee.
* #param {Object} employee - The employee who is responsible for the project.
* #param {string} employee.name - The name of the employee.
* #param {string} employee.department - The employee's department.
*/
Project.prototype.assign = function(employee) {
// ...
};
(Google Closure compiler type checking, that was based on but diverted from JSDoc, also allows #param {{x:number,y:number}} point A "point-shaped" object.)

Related

Codeigniter 4 filters don't works

hi i want create my own authorization to study the new veri=sion of framework ...
this is my route :
$routes->add('/user/login', 'User::login',['filter'=>'usersFiltersNoAuth']);
$routes->add('/login', 'User::login',['filter'=>'usersFiltersNoAuth']);
$routes->add('/user/registration', 'User::registration',['filter'=>'usersFiltersNoAuth']);
$routes->add('/logout', 'User::logout');
$routes->add('/user/changeEmail', 'User::changeEmail',['filter'=>'usersFiltersAuth']);
$routes->add('/user/changePassword', 'User::changePassword',['filter'=>'usersFiltersAuth']);
And this is my 2 filter class:
class UsersFiltersNoAuth implements FilterInterface
{
/**
* Do whatever processing this filter needs to do.
* By default it should not return anything during
* normal execution. However, when an abnormal state
* is found, it should return an instance of
* CodeIgniter\HTTP\Response. If it does, script
* execution will end and that Response will be
* sent back to the client, allowing for error pages,
* redirects, etc.
*
* #param \CodeIgniter\HTTP\RequestInterface $request
* #param array|null $params
*
* #return mixed
*/
public function before(RequestInterface $request, $params = null)
{
// if no user is logged in then send them to the login form
if (isset($_SESSION['user_id']))
{
return redirect()->to('/user/index');
}
}
//--------------------------------------------------------------------
/**
* Allows After filters to inspect and modify the response
* object as needed. This method does not allow any way
* to stop execution of other after filters, short of
* throwing an Exception or Error.
*
* #param \CodeIgniter\HTTP\RequestInterface $request
* #param \CodeIgniter\HTTP\ResponseInterface $response
* #param array|null $arguments
*
* #return void
*/
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
}
//--------------------------------------------------------------------
} // End of UsersFiltersNoAuth Class.
class UsersFiltersAuth implements FilterInterface
{
/**
* Do whatever processing this filter needs to do.
* By default it should not return anything during
* normal execution. However, when an abnormal state
* is found, it should return an instance of
* CodeIgniter\HTTP\Response. If it does, script
* execution will end and that Response will be
* sent back to the client, allowing for error pages,
* redirects, etc.
*
* #param \CodeIgniter\HTTP\RequestInterface $request
* #param array|null $params
*
* #return mixed
*/
public function before(RequestInterface $request, $params = null)
{
// if no user is logged in then send them to the login form
if (!isset($_SESSION['user_id']))
{
session()->set('redirect_url', current_url());
return redirect()->to('/login');
}
}
//--------------------------------------------------------------------
/**
* Allows After filters to inspect and modify the response
* object as needed. This method does not allow any way
* to stop execution of other after filters, short of
* throwing an Exception or Error.
*
* #param \CodeIgniter\HTTP\RequestInterface $request
* #param \CodeIgniter\HTTP\ResponseInterface $response
* #param array|null $arguments
*
* #return void
*/
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
}
//--------------------------------------------------------------------
} // End of UsersFiltersAuth Class.
if i try to go to /user/chengeEmail or /user/changePassword when ($_SESSION['user_id] is set) i am redirect to /user/index why ?
Moreover there is a way to apply a filter to an entire controller ? except some method ?

Action / GET with limited properties

Certainly already asked but...
Having this entity
/**
* A form
*
* #ORM\Entity(repositoryClass=FormRepository::class)
*
* #ORM\Table(
* name="forms",
* options={"comment":"Table of the forms"},
* indexes={
* #ORM\Index(name="forms_idx_dofc", columns={"dateofcreation"}),
* #ORM\Index(name="forms_idx_dofu", columns={"dateofupdate"}),
* #ORM\Index(name="forms_idx_dofs", columns={"dateofsubmission"})
* }
* )
*
* #ApiResource(
* routePrefix="/",
* shortName="Forms",
* description="API Access : form Entity",
* collectionOperations={"GET"},
* itemOperations={"GET"},
* attributes={
* "normalization_context"={
* "groups"={
* "GET:FORM"
* }
* },
* "order"={
* "dateofsubmission",
* "dateofupdate",
* "dateofcreation"
* }
* }
* )
*
*/
class Form
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer", options={"comment":"Primary Key, Auto generated"})
*/
private $id;
/**
* #var datetime Date of creation of the form.
*
* #ORM\Column(type="datetime", options={"comment":"date of creation of the form"})
*
* #Assert\NotBlank(message="The date time when was created the form should not be blank")
* #Assert\DateTime(message="The data time when was created the form should be the type DateTime")
*
* #Groups({"GET:FORM"})
*
* #ApiFilter(OrderFilter::class, strategy="ASC")
*/
private $dateofcreation;
/**
* #var datetime Date of update of the form.
*
* #ORM\Column(type="datetime", options={"comment":"date of update of the form"})
*
* #Assert\NotBlank(message="The date time when was updated the form should not be blank")
* #Assert\DateTime(message="The data time when was updated the form should be the type DateTime")
*
* #Groups({"GET:FORM"})
*
* #ApiFilter(OrderFilter::class, strategy="ASC")
*/
private $dateofupdate;
/**
* #var person Person that has created the form.
*
* #ORM\ManyToOne(targetEntity=Person::class, inversedBy="forms")
* #ORM\JoinColumn(nullable=false)
*
* #Groups({"GET:FORM"})
*
* #ApiFilter(SearchFilter::class, properties={"createdBy.id":"exact","createdBy.givenname":"ipartial", "createdBy.familyname":"ipartial"})
* #ApiFilter(OrderFilter::class, strategy="ASC")
*/
private $createdBy;
...
I would like to have the possibility of having :
A base collectionOperations "GET" would return all the properties that have the #GROUP=GET:FORM
A alternate collectionOperations "GETDATES" would return all properties that have a #GROUP=GET:DATES
The operations being accessible (ideally) with different routes.
GET => # http://api/forms?createdBy.id=25 => All properties
GETDATES => http://api/formsLimited?createdBy.id=25 => only the dates
ps: I hope this is better for the readability.
Thanks to Grégoire Hébert(https://stackoverflow.com/users/4887997/gr%C3%A9goire-hebert) for the support (on Slack).
The solution is quite simple.
Create in the ApiResource() a collection operation with:
Method = GET
path (that will become a route)
the normalization context for the group to be applied to the wanted properties
It gives:
collectionOperations={"GET","GETLIMITED"={"method"="GET","path"="formslist","normalization_context"={"groups"="GET:LIMITED"}}},

Laravel bindings - how to use call() method?

Could you give some example of usage of Laravel binding call() method? Below you have Laravel Container Interface call() method.
/**
* Call the given Closure / class#method and inject its dependencies.
*
* #param callable|string $callback
* #param array $parameters
* #param string|null $defaultMethod
* #return mixed
*/
public function call($callback, array $parameters = [], $defaultMethod = null);
I guess to work with that this way:
$this->app->call('how_to_use_this_params')
Thanks in advance.

Type error: Too few arguments to function createRoute(), 0 passed and exactly 3 expected in RoutesController

I'm working on Laravel 5.6,
I'm creating a function that receives three parameters ($name_route, $description_route, $photo_route) that I would like to be inserted on table Route, but I'm having the following error that can't explain:
"Type error: Too few arguments to function App\\Http\\Controllers\\RoutesController::createRoute(), 0 passed and exactly 3 expected in RoutesController.php (64)"
What am I doing wrong if I'm passing those three variables? I'm testing using Swagger.
Here's how I'm setting in my routes file (routes.php):
/** ***********************************************************
* Logged user can create a route
* ************************************************************
* #SWG\Post(
* tags={"Routes"},
* path="/api/v1/routes/route/create",
* summary="Logged user can create a route",
* #SWG\Parameter(ref="#/parameters/Accept"),
* #SWG\Parameter(ref="#/parameters/apikey"),
* #SWG\Parameter(ref="#/parameters/Language"),
* #SWG\Parameter(ref="#/parameters/Authorization"),
* #SWG\Parameter(name="name", in="path", type="string"),
* #SWG\Parameter(name="description", in="path", type="string"),
* #SWG\Parameter(name="photo", in="path", type="string"),
* #SWG\Response(response=HTTP_CODE_200_OK, description="Routes",
#SWG\Schema(ref="#/definitions/RouteDetail")),
* )
*/
Route::post('/route/create', 'RoutesController#createRoute')->middleware('auth:api');
And my controller:
/**
* #param $name_route
* #param $description_route
* #param $photo_route
*/
public function createRoute($name_route, $description_route, $photo_route)
{
$route = new Route();
$route->user_id = $this->input($this->user()->id);
$route->name = $this->input($name_route);
$route->description = $this->input($description_route);
$route->photo = $this->input($photo_route);
$route->save();
}

How to parse / validate / handle http headers in PHP

Currently i am building my own php framework and i am now creating an implementation of the PHP-FIG PSR-7 MessageInterface. In specific the withHeader method. It states that the method could trow an exeption: \InvalidArgumentException for invalid header names or values.
So i am wondering, when is a header valid or invalid? Same for the values.
Or should i accept any header, and any header value? That could be dangerous right?
I now you can generaly say that if a header has multiple values, they are comma seperated. But that does not allways apply. If i look at a user-agent header for example, the value itself sometimes contains a comma. But you should treat it as a single value.
Indeed, it's "dangerous" to pass a header name - as argument of withHeader(), which
is NULL
is not a string
is an empty string
The same applies to the header value argument. It must be an array or a string (representing only one value, not a comma-separated list of values!).
As for the implementation of the withHeader method:
/**
* Return an instance with the provided value replacing the specified header.
*
* ...
*
* #param string $name Case-insensitive header field name.
* #param string|string[] $value Header value(s).
* #return static
* #throws \InvalidArgumentException for invalid header names or values.
*/
public function withHeader($name, $value) {
$this
->validateHeaderName($name)
->validateHeaderValue($value)
;
$clone = clone $this;
$clone->replaceHeader($name, $value);
return $clone;
}
/**
* =================
* Not part of PSR-7
* =================
*
* Validate header name.
*
* #param string $name Case-insensitive header field name.
* #return $this
* #throws \InvalidArgumentException
*/
protected function validateHeaderName($name) {
if (!isset($name)) {
throw new \InvalidArgumentException('No header name provided!');
}
if (!is_string($name)) {
throw new \InvalidArgumentException('The header name must be a string!');
}
if (empty($name)) {
throw new \InvalidArgumentException('Empty header name provided!');
}
return $this;
}
/**
* =================
* Not part of PSR-7
* =================
*
* Validate header value.
*
* #param string|string[] $value Header value(s).
* #return $this
* #throws \InvalidArgumentException
*/
protected function validateHeaderValue($value) {
if (isset($value) && !is_array($value) && !is_string($value)) {
throw new \InvalidArgumentException('The header value must be a string or an array!');
}
return $this;
}
/**
* =================
* Not part of PSR-7
* =================
*
* Replace a header item with a new one.
*
* #param string $name Case-insensitive header field name.
* #param string|string[] $value Header value(s).
* #return $this
* #done
*/
protected function replaceHeader($name, $value) {
$this
->removeHeader($name)
->addHeader($name, $value)
;
return $this;
}
You can find that in RFC 7230. Check Zend Diactoro's HeaderSecurity class for an implementation.

Resources