I'm looking to build my project in a modular fashion so that API endpoints can be added while the server is added.
Adding routes dynamically I should be able to figure out, it's getting the recently uploaded server code running that I can't figure out.
My project has a 'class-per-endpoint' structure. An endpoint has a class attached that can run code and do this and that.
An endpoint can also be dependent on another endpoint/class, so what I want to be able to do is call the constructor of a dynamically added class and run the code efficiently on the server (without the API calling itself).
Example where "NewAdder" endpoint was just added. Rudimentary stuff, but I just hope it's clear what I'm trying to achieve. Basically trying to add to the server's code base dynamically.
modifier.ts
class Modifier {
constructor(initiatedBy) {
this.initBy = initiatedBy;
this.modifierValue = db.getValue("modifier", {user = this.initBy})
}
function modify(toModify) {
return toModify * this.modifierValue
}
}
newAdder.ts
class NewAdder {
constructor(initiatedBy) {
this.initBy = initiatedBy;
}
modifier = new Modifier(this.initBy);
function addAndModify(a,b) {
return modifier.modify(a + b)
}
}
router.ts (this would be dynamic in real life)
app.get('/newadder/addandmodify/', function(req, res){
adder = new NewAdder(req.params.user);
res.send(adder.addAndModify(req.params.first, req.params.second);
});
Hope I made some sense.
After some more research I suppose I could use http to get and then require the module dynamically.
The code will come from our own server, so it should be safe to run in the server.
But if anyone has any idea how to go about this, would be much appreciated.
Related
Probably everyone was facing the issue when Postman documentation will be barely up-to-date with the code currently running in dev or production.
Almost every time the source of that problem is "a little change" or adding a new column into the database.
So I would like the code to be self-documented, starting from the validator.
There is the wrap-implementation over the JOI validator
class Validator {
_schema = {};
static TYPES = Joi;
setRule(field, rule){
this._schema[field] = rule;
}
validate(data){
let schema = Joi.object(this._schema);
try {
Joi.assert(data, schema, {abortEarly: false});
}
catch(error){
const message = error.details.map(detail => detail.message);
throw new ValidationError(message);
}
}
}
The controller uses this wrap just like that
const validator = new Validator();
validator.setRule('sts', Validator.TYPES.string());
validator.validate(body);
Every time the crucial code change happens, it usually affects the incoming body validation.
So the idea behind self-documentation is why not to use validator class as a source of the API documentation? We could get almost every piece of information about the endpoint using router + validator.
But how can you collect the data about that for every endpoint (especially, controller).
We should somehow get access to every instance of the Validator class inside each controller?
Or shall we just read the source file to get an information about the rules?
There are several implementations of Swagger-like docs, but they are all based on decorators code style, from which we are trying to get rid of.
Recently, I have been working on a personal project involving the creation of some API endpoints using NextJs and TypeScript that call back on the Discord API using discord.js. Please don't get scared off at the mention of the discord API if you have never touched it, I don't think that library is the issue, hence why it is not included in the thread title.
Problem:
I have implemented a singleton for the discord.js API client as the client can take about a second or two to login and initialize, time I don't want to add to each response. This works great on one file/endpoint, where once that file has the instance, it keeps its. However, as soon as I load another file/endpoint, it creates another instance of the singleton, however, after its creation works fine again within that file.
My problem is that I dont want an instance per file, but instead want one instance for the entire application.
DiscordClient.ts:
import { Client } from 'discord.js';
class DiscordClient {
private static discordClient: DiscordClient;
public APIClient: Client;
private constructor() {
this.APIClient = new Client();
this.APIClient.login($TOKEN);
}
public static get Instance() {
if (!this.discordClient) {
this.discordClient = new DiscordClient();
}
return this.discordClient;
}
}
export const DiscordClientInstance = DiscordClient.Instance;
NOTE: token is merely a placeholder for the unique token of my bot application registered with discord.
/pages/api/test1.ts
import { DiscordClientInstance } from "../../DiscordClient";
export default (req, res) => {
let guild = DiscordClientInstance.APIClient.guilds.fetch($GUILD_1_ID)
.then(guild => {
console.log(guild.name);
res.statusCode = 200;
res.json({ name: guild.name });
})
.catch(console.error);
}
/pages/api/test2.ts
import { DiscordClientInstance } from "../../DiscordClient";
export default (req, res) => {
let guild = DiscordClientInstance.APIClient.guilds.fetch($GUILD_2_ID)
.then(guild => {
console.log(guild.name);
res.statusCode = 200;
res.json({ name: guild.name });
})
.catch(console.error);
}
NOTE: $GUILD_#_ID is merely a placeholder for where the the id of the discord server I am fetching would go.
As can be seen above, test1.ts and test2.ts are nearly identical and are inheriting the same const.
If anyone had any clues as to why this is happening, I would be very appreciative. Some people on other sites from my late-night googling have suggested this could be an issue with node, however, I honestly have no clue.
Thanks,
Matt :)
I use this very pattern without issues - Have you tried this in production mode? When in development mode Next.js will compile each page on-demand which I've observed breaking this pattern. Essentially, if you see "compiling..." then you've lost your persistence. In production mode this doesn't happen and you should see your single instance persisted.
A logger is implemented as a middle-ware. Need to access the output of the logger through another dialog.
Look at the Botbuilder-Samples repo, the 17.multilingual-conversations sample. It demonstrates how you can interact with the dialog by receiving and sending activities based around the current context and inputs.
First, assign your middleware to the adapter in the index.js file:
const { LoggerMiddleware } = require('./logger-middleware');
adapter.use(new LoggerMiddleware (parameter_1, parameter_2));
Like the translator-middleware.js file, you will want to pass any necessary parameters thru the constructor of your middleware file:
constructor(parameter_1, parameter_2) {
this.parameter_1 = parameter_1;
this.parameter_2 = parameter_2;
}
After which, you create the onTurn method (and any associated methods), passing in the context and utilizing the class constructor parameters you need. Here you can create new dialogs that make use of the passed in logged data.
async onTurn(turnContext, next) {
let loggerText = this.parameter_1;
[...do stuff with <loggerText> data...]
await next();
}
In many respects, the middleware looks and functions like your main bot.js file. It is simply called at a different point in the process.
Hope of help.
I'm newbie in Sails JS..
I'm trying to create a new custom response, I didn't find any auto-generator so I created it manually.
//someName.js
module.exports = function someName(data, options) {
console.log('test');
};
I'm trying to access this response from controller:
//someController.js
module.exports = {
someController: function(req, res) {
res.someName();
}
}
The problem is that WebStorm isn't recognize this response..
Unresolved function or method someName.
But when executing the app-it's working..(WebStorm recognize the default responses which came with the 'sails new someApp').
Thanks for your help!
The code in the Sails.js library that loads custom responses probably does something like this:
files = getFilesInApiResponsesDirectory()
files.forEach(function(file) {
name = extractName(file);
res[name] = require(file); // <-- too dynamic to infer at this point
})
There is no way that WebStorm code analyzer could infer the relationship between res and your custom response function without actually running Sails.js code or receiving a (less dynamic, more explicit) hint.
Anyway, the message you got does not necessarily represent a critical error, it's a "code inspection" you can disable or suppress.
new at this.
I have 2 div's;
When I use one to post new value into the server, the post action works fine.
How do ensure this post updates the scope in the other div? (to update the div with the new entry using ng-repeat)
The HTTP.post action seems to be working as the data appears on refresh.
I have tried $scope.apply() but it doesn't appear to be working.
// this is the controller to get the data from the server
app.controller('projectsController',
function projectsController($scope, projectsFactory){
$scope.projects = projectsFactory.query();
});
and the factory to get the data from server
app.factory('projectsFactory',
function($resource,localStorage, $rootScope, $http){
return $resource('/api/project:id', {id: '#id'});
});
This is the controller to take the user input and post to back to the server
app.controller('projectEditController', function($scope, projectEdit){
$scope.projectEdit = projectEdit;
});
And the service to post the data to the server
app.service('projectEdit',
function projectEdit(localStorage,$rootScope, $http) {
var self = this;
self.add = function(newProject,projects) {
newProject = angular.copy(newProject);
var newProject = (JSON.stringify(newProject));
return $http.post('/api/project', newProject )
.then(function(response) {
newProject.id = response.data.id;
});
};
Which seems to be fine as it posts the data to the Sever fine.
What I am trying to figure out is how to get the
"$scope.projects = projectsFactory.query();" to update once the post operation is complete.
this will update the display in the HTML, which is the goal.
Hopefully this is an easy solve for a good developer, but I am stumped!
Thanks for your time.
Conor
Create 1 wrapper div, and set your controller to it with ng-controller.
Put your 2 divs in the wrapper div. Now the scope created by your controller is available in both divs, this is the easy way. When something updates data in that scope, and you have other things in the dom referencing that variable, then the dom will refresh like you want.
If you really want different controllers for each child div, that's fine, just be careful around inherited scopes. It really is much easier to just have one controller in a situation like this.
By the way, I saw that you mentioned scope.apply(). Be careful, apply() is a real javascript function, and NOT the one you want. You should call scope.$apply(), $apply is the angular function, and to avoid confusion, you could call scope.$digest instead.