Auto loading routes in HapiJS - node.js

I was wondering if anyone has a way to automatically and programmatically load HapiJS routes automatically. I was looking for a way that would be something like the routes that fall under a specific resource all go in a js file named after that resource.
For example, if I had a file src/routes/account.js, which would have the routes /login and /register, which would create the API routes /account/login and /login/register.. Or something that would let me have a programmatic way of automatically loading the routes.
I use Actin to load my controllers, and I was hoping to use something similar to that. I didn't see any plugins that could accomplish this, so I thought id ask if someone has a method for this already
Thanks!

I couldn't find anything that would load routes programmatically, using a folder structure to help with the route hierarchy, so I created my own.
It's not a full HapiJS plugin yet, but heres the code if anyone wants to use it.
Basic Details
Load the routes.js file as a HapiJS plugin (from the /dist folder, for ES5 transpiled version)
You can load it any way you want, I use Confidence to load it in the configuration file
Create a *Routes folder to contain your routes, make sure it's in the same folder as the routes.js file (Ill make an option so you can specify the routes folder later)
Create some js files that export some HapiJS routes (like so).
Keep in mind that the path in the route files will be appended to the path from the routes folder. Meaning if you have a file at src/routes/users.js, and it has a route with the path /list, then the real path will be /users/list
To define a Root Resource, then define the rootResource in the settings (Value should be the file name without the .js extension)

Take a look at hapi-auto-route. This package loads routes automatically and add prefix to the route path

Related

Serve static files with ExpressJS Typescript NodeJS

I'm trying to serve static file uploaded using ExpressJS and NodeJS with Typescript but getting 404 error.
the file I want to read is ./src/data/uploads/test.txt and I'm trying to access it from web browser directly.
Note: When I do it in Javascript it worked but not in Typscript.
index.ts file (app entry point)
import express from 'express';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import {cdg, config} from './utils';
import {Mongoose} from './db/monogdb';
import { setRoutes } from './routes/route.decorators';
import cors from 'cors';
import './routes';
const app = express();
app.use(helmet());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/ftp', express.static('data/uploads'));
setRoutes(app);
app.listen(config.server.port, () => {
cdg.konsole("Server connected! :: " + config.server.port + "!");
});
Is there a specific way to serve static file with Typescript ?
Here's how express.static() works. You are apparently missing one of these steps, but your question is short of the details to identify exactly which step is not correct.
First, you define an express.static() middleware that contains some parameters. In your case, you've defined this:
app.use('/ftp', express.static('data/uploads'));
There are four elements that determine how this works:
The /ftp that must be at the start of any URL for this middleware to match.
The incoming URL request and how it was formed by the browser based on how you specified it in your HTML.
The current working directory that is combined with data/uploads to make a full path reference or you could build your own absolute path and not depend upon the cwd.
The files in cwd + /data/uploads that express.static() will attempt to match to the path of the incoming URL.
Let's look into these further:
Your middleware will first only look at URLs that start with /ftp. And, then for any URL it sees that does start with /ftp, it should take the rest of the URL and append it to data/uploads and see it finds a matching file in your local file system. It will use the current working directory in your server process at the time of the request to try to resolve the relative path data/uploads. That current working directory (if you haven't programmatically changed it) will depend upon how your app was started.
So, if you started your app with node index.js, then the current working directory will be the directory where index.js is located and express static will be looking in the data/uploads sub-directory below where 'index.js` is.
Then, we need to look at how the HTML tag that specifies this static resource is specified.
Let's say this is an <img> tag for example. If you specify something like this:
<img src="/ftp/hello.jpg">
Then, the browser will create a request to your server for /ftp/hello.jpg. Since that does start with /ftp, your express.static() middleware will take the rest of the path /hello.jpg and append that to data/uploads and build a path that looks like this:
path.join(process.cwd(), 'data/uploads', '/hello.jpg')
And, it will look for that resulting file in your local file system. If it finds that file, then it will serve that file and return it as the response. If it doesn't find that exact file, then it will call next() and continue routing to your other route handlers.
There are a number of common mistakes (things that can go wrong):
You don't specify the correct URL in your web page that lines up with your express.static() middleware line (including the /ftp prefix that your middleware specifies).
Your middleware isn't quite pointing at the right directory in your file system so it never finds anything.
You are using relative URLs in your web page which the browser combines with the path of your web page causing it to request something different than you want. Static resource URLs in your web page should nearly always start with / so they are not dependent upon the path of the parent page.
The files aren't quite properly located in the file hierarchy you are pointing to with your middleware (often off by one level).
One other thing I will mention. Since you're using TypeScript, that means you have to compile/build your script into a regular .js script before it can be run. This will typically be in a different directory location.
This different directory location creates opportunities for you to not be referencing the proper directory where your static resources are, since they are probably located relative to your TypeScript files, not the built Javascript files that you're running (that depends upon your build script).
Again, if you show us where everything is in your file system (TypeScript files, built JS files, static resources) and what the HTML tag that references the static resource looks like, we can help you debug that more specifically.
In my case I solved my problem like this: in the parameter relative to the directory path I used path.resolve and in its first parameter I used __dirname as the first parameter and the relative path of the target directory as the second one.
app.get('/', express.static(path.resolve(__dirname, '../static/'))); –

NestJs Microservice - Which location do I read files from?

Wondering if anyone can help? I am trying to learn how to use NestJS microservices. I have managed to succesfully get a microservice with MQTT transport setup to receive events from an API. I am trying to use pug to merge the event information with a html template file. However pug cannot find the template file...
this.logger.info(`Running from dir ${__dirname}`); // /usr/src/app/dist/apps/microservice
const template = pug.compileFile('../templates/email.pug');
I have used a logger to display __dirname which refers to the dist directory. This has the single file main.js inside. How do I bundle and read a template pug file from nestjs microservice?
This post has a similar question, however it is for a nestjs app.
First we need to configure the express instance
// main.ts
const app = await NestFactory.create<NestExpressApplication>(
AppModule,
);
app.setViewEngine('hbs');
Put templates folder in root with the neighborhood src folder
but you must find it not in dist folder because Typescript compiler dont copy non-typescript files to dist folder for that approach you can use copy-webpack-plugin
but i just advise you change this url( ../templates/email.pug) so that to find folder located in root not find it in dist
hope it will help you! if not please provide your file structure.
https://docs.nestjs.com/techniques/mvc

Sails JS add routes dynamically

I'm trying to find a way to add routes dynamically outsides of the config/routes.js file.
I'm creating a module who need some routes and don't want to let the user add it manually under config/routes.js.
Is there a way to do this ? I look sails doc and maybe with hooks I can't achieve this but can't find how
Thanks
I'm curious What kind of routing path you want to create?
Remember that wildcard is available in route.js
'GET /validEmail/*', "VerificationController.verifyEmail"'

What is index.js used for in node.js projects?

Other than a nice way to require all files in a directory (node.js require all files in a folder?), what is index.js used for mainly?
When you pass a folder to Node's require(), it will check for a package.json for an endpoint. If that isn't defined, it checks for index.js, and finally index.node (a c++ extension format). So the index.js is most likely the entry point for requiring a module.
See the official Docs here: http://nodejs.org/api/modules.html#modules_folders_as_modules.
Also, you ask how to require all the files in a directory. Usually, you require a directory with an index.js that exposes some encapsulated interface to those files; the way to do this will be different for ever module. But suppose you wanted to include a folder's contents when you include the folder (note, this is not a best practice and comes up less often than you would think). Then, you could use an index.js that loads all the files in the directory synchronously (setting exports asynchronously is usually asking for terrible bugs) and attaches them to module.exports like so:
var path = require('path'),
dir = require('fs').readdirSync(__dirname + path.sep);
dir.forEach(function(filename){
if(path.extname(filename) === '.js' && filename !== 'index.js'){
var exportAsName = path.basename(filename);
module.exports[exportAsName] = require( path.join( __dirname, filename) );
}
});
I hardly ever see people wanting to use that pattern though - most of the time you want your index.js to go something like
var part1 = require('./something-in-the-directory'),
part2 = require('./something-else');
....
module.exports = myCoolInterfaceThatUsesPart1AndPart2UnderTheHood;
Typically in other languages the web server looks for certain files to load first when visiting a directory like / in priority, traditionally this is either: index or default. In php it would be index.php or just plain HTML it would be index.html
In Node.js, Node itself is the web server so you don't need to name anything index.js but it's easier for people to understand which file to run first.
index.js typically handles your app startup, routing and other functions of your application and does require other modules to add functionality. If you're running a website or web app it would also handle become a basic HTTP web server replacing the role of something more traditional like Apache.
Here is a good article explaining how Node.js looks for required module https://medium.freecodecamp.org/requiring-modules-in-node-js-everything-you-need-to-know-e7fbd119be8, with folder and index.js file
Modules don’t have to be files. We can also create a find-me folder
under node_modules and place an index.js file in there. The same
require('find-me') line will use that folder’s index.js file:
~/learn-node $ mkdir -p node_modules/find-me
~/learn-node $ echo "console.log('Found again.');" > node_modules/find-me/index.js
~/learn-node $ node
> require('find-me');
Found again.
{}
>
Late to the party but the answer is simply to allow a developer to specify the public api of the folder!
When you have a bunch of JavaScript files in a folder, only a small subset of the functions and values exported from these files should exportable outside of the folder. These carefully selected functions are the public apis of the folder and should be explicitly exported (or re-exported) from the index.js file. Thus, it serves an architectural purpose.

Getting started with Chaplin and node.js

Is there a way to use Chaplin with node.js/express? I haven't found a single tutorial or an example on this subject.
If so, how do I get started? How would the folder structure look like? Or my server.js file?
Chaplin appears to be purely client side. For a basic app your back end could be a static HTML page. It requires no particular server structure.
Backbone, which it's built on, expects a RESTful JSON API to persist its models, but otherwise doesn't require a backend either. If your app has models which need to be saved (likely), then you'll want to look into tutorials for writing a REST API in express (there are many) or for extending Backbone to suit your particular backend needs.
So to get started, your server.js file will look exactly like the one created by the express install script.
There's no de facto best practice for how to structure the folders in an end-to-end javascript app. In my experience I tend to keep client side javascript in its own folder (/client, /app/client, /lib/client, etc), then generate the publicly exposed compressed/concated scripts in a build step. To get started, you might just deposit them in /public/javascripts.
I still don't understand this..
In my express file it says
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
Should I move all my chaplin app files into that views folders or how do I launch them?
Anyway, express seems to use this jade thing but chaplin does not, how does that go?
My problem is to understand where everything goes and why.
Express creates it's own folder structure:
node_modules
public
routes
views
app.js
then again chaplin has it like this:
app
generators
bower.json
config.json
etc.
in that app folder:
assets
controllers
lib
models
views
Now, where do I place all of this chaplin stuff in my node folders? under public or views or where?
And then how do I get this whole thing started? Do I just include all the chaplin .js files in that index file I have in my node.js views folder (jade file)?

Resources