Access controller methods from sails service? - node.js

I have a function declared in a controller but outside of it, so it's a regular method not an action/api.
Let's say it's just does a console.log().
I need to access it from a sails service.
I've tried using sails.controllers.user.myFunction(). UserController being the function but I get 'undefined is not a function'.
Is there a way to do this?

The way I know to do it is like this (depending on where you are getting it your path could change, I put my test in the services folder):
var controller = require('../controllers/UserController.js');
controller.myFunction( );
I hope this helps!

Related

fastify-swagger is not picking up my dynamic routes

I've been a fan of ExpressJs for a long time but in a Youtube video I stumble upon Fastify and wanted to give it a try
I'm struggling in making the fastify-swagger plugin work as I assume it should work - dynamic setup to pick up the schema from each route, but I'm certainly missing something 😔
here's my test repo that after running, none of my routes appear
my setup for the plugin is the default one
but all I see is
I've read in the read me that because of OpenAPI specs, some properties, like description are mandatory or will not pick up the route, but I've added in one route, and still does not pick up, I've also added tags wondering if that was also mandatory, but nothing...
does anyone know what am I missing? must be a simple thing, but got me puzzled this last few days 😔
I ran into the same issue and ended up solving it by following the first Usage example line-by-line: https://github.com/fastify/fastify-swagger#usage
const fastify = require('fastify')()
(async () => {
// set up swagger
await fastify.register(require('#fastify/swagger'), {
...swagger config
});
// define all your routes
// then call these
await fastify.ready()
fastify.swagger()
})();
Consider the order in which your plugins are loaded, the routes need to be registered before fastify swagger. If fastify swagger comes first, it doesn't detect any route.
I encountered this issue in my project. In my case, I solved it using fastify-plugin. Looking at the source code for fastify-swagger, it seems to rely on a hook listening for onRoute events to detect routes. I'm thinking maybe encapsulation can interfere with the plugin's ability to receive the events.

Express + Typescript. Call controller from another controller

So I have a controller which I want to call from another controller. As you can see I trying to pass parameter {params: {task_id: String(task_id), result}}, but typescript complains that res doesn't have all attributes. How can I make it?
I suggest that you encapsulate the common logic in another function (which's not a controller but a service) and use it in both getCommentById and getCommentsSocketListener.
Every controller needs a response and request object and there's no good way of skipping it.

Change server option in middleware

In Fastify I can specify instance options while creating it, e.g.
const fastify = require('fastify')({logger:true, disableRequestLogging: false});
Is it possible to do this in a middleware registered with the instance?
e.g. if I do something like
fastify.register(myPlugin);
and instance of fastify is passed to myPlugin - can I, for example change its disableRequestLogging value while in the middleware?
The router is the what relies on disableRequestLogging to switch on/off logging for the request and the later response.
if (disableRequestLogging === false) {
childLogger.info({ req: request }, 'incoming request')
}
The router does provide a setup function that allows disableRequestLogging to be changed. You can see fastify.js uses router.setup() late in initialisation here to apply some new values.
The problem is fastify doesn't provide access to router as part of it's public API. Only functions like fastify.get/.post/.route etc which allow access to specific components of the router.
Short of modifying the source, I can't see a way. Not even something dodgey like onkeypatching a function in due to the way fastify variables are scoped. Even if you could do that, it would be delving into undefined/untested behaviours.

Sails call one controller from another controller

I am having two controllers, SocketController and ProjectController
SocketController has method getData(data)
ProjectController has method addProject(data)
I need to call addProject() from getData() method.
I tried using sails.controllers.ProjectController.addProject(data) but I got following error:
Cannot find method addProject of undefined
I searched for alternative ways to call another controller using services in Stack Overflow but that was of no help to me. Is there any other way to get this work?
Controllers are just Node modules that export public methods. You can require them like anything else. So assuming your methods are correctly exposed with module.exports, this will work:
/* ProjectController */
module.exports = {
addProject: function(data) {
// ...
}
};
/* SocketController */
// Assuming ProjectController.js exists in the same directory (default for Sails)
var projectController = require('./ProjectController');
module.exports = {
index: function(req, res) {
// ...
projectController.addProject(...);
}
};
Edit: I will add that using services is a better place to keep common functionality like your example. Services allow complex logic to be decoupled from the controller layer and reused by other areas of the application with ease. Controllers should generally be reserved for handling HTTP requests from the client and passing the data to the service or model layers for manipulating the database. I believe Sails also makes services global by default so you don't have to worry about confusing require paths.
Controller functions are also accessible through the global sails object, without use of require, however a function from ProjectController will be found under:
sails.controllers.project.addProject
instead of
sails.controllers.ProjectController.addProject
Anyways you might want to consider having shared functionality in either services or models, as was pointed out previously.

How to use a callback array as the handler for a Sails.js route?

When using Express, it is possible to attach a callback array to a route like this:
app.get('/path', thisIsAnArrayOfFunctions);
And then, when making a request to http://route_to_server/path each function inside thisIsAnArrayOfFunctions is called.
Exactly how does that routing behaviour works in express? is it just an iteration through thisIsAnArrayOfFunctions, passing the arguments req, res and next?
Is it possible to achieve a simple implementation in Sails for this?
I know it works if I attach the routing as an express middleware, but I want to know if there's a solution using the Sails' (version 0.9.8) controller structure.
Thanks in advance.
The Sails-y way of chaining functions to a route is by using policies. The idea is that your controller code should be the last stop in handling your route. Anything that might modify the response (like a login check, or something that could change the params) should be implemented as a policy, which is middleware that can call next or send a response directly. Policies are mapped to controller actions, and multiple policies can be applied to a single action (or to all actions in a controller).
Docs for policies are here.

Resources