All Projects → shy2net → nodejs-angular-starter

shy2net / nodejs-angular-starter

Licence: other
A starter template to work with on NodeJS (typescript), Angular (with SSR), and shared models.

Programming Languages

typescript
32286 projects
HTML
75241 projects
shell
77523 projects
javascript
184084 projects - #8 most used programming language
Dockerfile
14818 projects
SCSS
7915 projects
CSS
56736 projects

Projects that are alternatives of or similar to nodejs-angular-starter

frontenso-11ty-starter
Production-ready 11ty+Gulp+Webpack Starter that features Nunjucks, SASS, TailwindCSS (with JIT complier), and ESNext.
Stars: ✭ 24 (+84.62%)
Mutual labels:  starter-template
angular-seat-charts
Angular Seat Charts Generator
Stars: ✭ 33 (+153.85%)
Mutual labels:  angular6
vue-h5-template
H5 开发的 vue 项目快速启动模板
Stars: ✭ 23 (+76.92%)
Mutual labels:  starter-template
AuthGuard
Example repo for guarding routes post
Stars: ✭ 42 (+223.08%)
Mutual labels:  angular6
dynamic-app
Dynamic Forms Builder are reusable and make building large-scale applications easier (Easy Peasy)
Stars: ✭ 15 (+15.38%)
Mutual labels:  angular6
ng-xform
esss.github.io/ng-xform/home
Stars: ✭ 18 (+38.46%)
Mutual labels:  angular6
nextarter-chakra
battery packed template / boilerplate to initialize Next.js app with Chakra UI & Typescript setup ✨
Stars: ✭ 616 (+4638.46%)
Mutual labels:  starter-template
phaser-3-vsc-typescript-nodejs
Template for a new Phaser 3 project with Visual Studio Code, TypeScript, and Node.js.
Stars: ✭ 18 (+38.46%)
Mutual labels:  starter-template
ng-walkthrough
A walkthrough for Angular
Stars: ✭ 21 (+61.54%)
Mutual labels:  angular6
react-you-do-you
How I use React + Redux + Material-UI + TypeScript – you do you 💖
Stars: ✭ 103 (+692.31%)
Mutual labels:  starter-template
sass-starter-pack
Sass starter files using Gulp v4.0.0 🔥
Stars: ✭ 34 (+161.54%)
Mutual labels:  starter-template
file-input-accessor
Angular directive that provides file input functionality in Angular forms.
Stars: ✭ 32 (+146.15%)
Mutual labels:  angular6
Ecommerce
Angular 6 Ecommerce Application POC
Stars: ✭ 46 (+253.85%)
Mutual labels:  angular6
nextjs-dapp-starter-ts
A fullstack monorepo template to develop ethereum dapps
Stars: ✭ 228 (+1653.85%)
Mutual labels:  starter-template
vueuse-vite-starter
⚡️ Starter for Vite + VueUse + TypeScript
Stars: ✭ 121 (+830.77%)
Mutual labels:  starter-template
Rainblur-Landing-Page
Tailwind CSS Starter Template - Rainblur Landing Page (dark)
Stars: ✭ 112 (+761.54%)
Mutual labels:  starter-template
laravel-startkit
Laravel Admin Dashboard, Admin Template with Frontend Template, for scalable Laravel projects. It is to save your time when You start with new scalable Laravel projects with many features Bootstrap, cooreui, infyom admin Generator, roles and permissions, translatable models, spatie media and much more
Stars: ✭ 55 (+323.08%)
Mutual labels:  starter-template
flowchart-angular6
一个基于jsplumb的使用angular6写的一个可拖拽的流程图实例
Stars: ✭ 46 (+253.85%)
Mutual labels:  angular6
react-admin
基于React + ant-design的用作后台管理项目的脚手架
Stars: ✭ 96 (+638.46%)
Mutual labels:  starter-template
react-redux-boilerplate
React, Redux Boilerplate with authentication
Stars: ✭ 35 (+169.23%)
Mutual labels:  starter-template

Important Note

This template is deprecated and will no longer be maintained. Please use the new nest-angular-starter instead. It has almost the same code-base except the server side which was refactored and is now based on NestJS.

It is highly recommend to move to the new template instead, as this template is no longer maintained!

Introduction

This starter template comes with NodeJS (typescript) and Angular 10. It shares models between Angular and NodeJS. Both of the NodeJS and and Angular 10 can run on the same webserver as the NodeJS exposes all of the default routes to Angular and all of the known routes to the api.

Technologies used in this template:

  • Angular 10 (with SSR) - including unit tests (based on Jasmine + Karma)
  • NodeJS express typescript (with SSL support) based on Ts.ED - for easier express setup using decorators
  • Mocha + Chai for backend testing + API tests
  • Mongoose (with basic user model)
  • Logging (using Ts.LogDebug)
  • Bootstrap v4 and SCSS by default
  • JWT and token authentication built-in (including user roles)
  • Social Authentication (Google and Facebook)
  • Form validations using (class-validator), shared between server and client
  • Docker support based on alpine and node 12

Prerequisites

In order to start with this template you have to set up the environment you are working on to suit the needs.

All environments

Because this template uses mongo-db by default, if you want to run it easily out-of-the-box you must install docker, then run the following command:

docker-compose up -d db # Loads up an instance of mongo-db locally with root\root (user\pass) and 'admin' database

This will create a simple mongo database with a username\password of 'root' and database named 'admin'. The mongo-db instance will create a volume mounted at: ~/web_mongo (inside your user home directory) Optionally, you can connect to your own mongo-db instance by configuring it (read the config section for more).

On Windows

Make sure to install git bash, this allows you to run bash commands which are essential for the build process. You can use any other bash for windows, as long as it can run the scripts this template relays on (./install_all.sh, predebug.sh, build.sh, test.sh).

Make sure to add bash to your system 'PATH'.

On Linux

After cloning this repository, make sure to run the following command:

chmod +x ./install_all.sh && chmod +x ./predebug.sh && chmod +x ./build.sh && chmod +x ./test.sh

This will give permission to run all included required to work with this template.

Starting with this template

To work with this template locally (debug mode), follow these commands:

npm run install:all # Install all dependencies required for both NodeJS and Angular
npm run node # Run the NodeJS on debug mode
npm run angular # Run Angular

We don't run the npm start command as it is reserved only for the compiled code to run on a production server.

In order to compile and build this template for your production server run the following:

npm run install:all # Install all dependencies required for both NodeJS and Angular
npm run build # Run the build.sh script to compile and NodeJS and Angular for production
npm start

These list of commands will install, compile and run the output NodeJS.

Template architecture

The template comes with a ready to go server and client integration, authentication and basic styling.

Angular 10

Angular 10 comes with the following features:

  • Bootstrap v4 with header and sticky footer.
  • Built in SSR bundled with the api server.
  • Built in toasty (ngx-toastr) which automatically pops up on HTTP errors obtained from the server API.
  • Built in ngx-loading-bar (Youtube styled) when moving between routes.
  • Built in auth-guard and authentication, saved on session cookie.
  • Built in social authentication (Google and Facebook).
  • Build in form validations using class-validator (https://github.com/typestack/class-validator) implemented using the FormValidatorDirective.

The code of Angular 10 is stored under the angular-src directory.

Angular services & providers

This template comes with multiple services and proviers which can be used accross the template.

  • ApiService - This service wraps the access to the server api. It should contain a 'mirror' of the functions that the server has.
  • AuthService - This service exposes all of the authentication mechanisem and handles all of the login, including login to the api, obtaining the token and saving the token to a cookie for next refresh.
  • AuthGuardService - An auth guard which used the AuthService to guard routes. It also comes with role checking by specifing the typescript { roles: ['roleName'] } data for your route.
  • AppHttpInterceptor - This provider acts as an interceptor for all of the http requests ongoing. It adds the authentication token if provided by the AuthService to each request. Then it passes the request to the RequestsService to handle.
  • RequestsService - This service handles all of the requests passing through using the AppHttpInterceptor. It shows an error toast if an error had occured in one of the requests.
  • AppService - Holds information about the current user and app related data.
  • SocialLoginService - This service is responsible for the whole social authentication (Google and Facebook), it uses angularx-social-login module to do so. This service can be found under social-login module which initializes all of the providers (which are the 3rd party social sites).

Angular components

  • AppComponent - The app component is the bootstrap component of this template. It contain the HTML of the app (such the header, router-oulet and footer). It contains logic to listen to routing changes and showing or hiding the slim loading bar (Youtube styled routing progress bar).

  • HeaderComponent - The header part of the template. It shows a simple header based on bootstrap which is suitable for mobile as well.

  • FooterComponent - A simple sticky footer that always appear at the bottom of the page.

  • LoginComponent - A simple login with username and password which authenticates against the server.

  • UserPageComponent - A simple page that shows information about the currently logged in user with option of logging out.

  • SocialLoginButton - A simple container of social login buttons which also performs the social authentication itself.

Angular Universal (Server-Side-Rendering)

By default this template comes ready with Angular Universal which allows search engines to crawl your website better. It does this on the NodeJS side after running the npm run build command which bundles the angular code and create an angular universal express ready file called out/src/dist/server.js which our NodeJS simply imports and initializes in the src/app.ts file.

in the src/app.ts you have these two methods:

  /**
   * Mounts angular using Server-Side-Rendering (Recommended for SEO)
   */
  private mountAngularSSR(): void {
    // The dist folder of compiled angular
    const DIST_FOLDER = path.join(__dirname, 'dist');

    // The compiled server file (angular-src/server.ts) path
    const ngApp = require(path.join(DIST_FOLDER, 'server/main'));

    // Init the ng-app using SSR
    ngApp.init(this.expressApp, path.join(DIST_FOLDER, '/browser'));
  }

  /**
   * Mounts angular as is with no SSR.
   */
  private mountAngular(): void {
    // Point static path to Angular 2 distribution
    this.express.use(express.static(path.join(__dirname, 'dist/browser')));

    // Deliever the Angular 2 distribution
    this.express.get('*', function(req, res) {
      res.sendFile(path.join(__dirname, 'dist/browser/index.html'));
    });
  }

By default the mountAngular is called in the init method of src/app.ts, simply change it into mountAngularSSR in order to enable SSR, but be careful as SSR requires special treatments in your code on certain situations.

NodeJS

Comes with built in typescript support and compilation.

It comes with the following features:

  • Ts.ED - Easier express with typescript using decorators
  • Authentication (including middlewares and token generation)
  • Angular routes support (redirect to index.html of compiled Angular code), this means you can run you Angular app and API on the same container!
  • Configuration according to environment (using config npm package).
  • Logging (using Ts.LogDebug).
  • Social Authentication, which basically gets an access token from the client that logged into a service and then creates a user associated with it.
  • Unit testing using Mocha and Chai.

The code of NodeJS is stored under the src directory. Output directory of the compiled typescript will be available in the out directory.

How the API works

I would first recommend you to read the Getting Started tutorial of Ts.ED. As it will explain really good how the decorators help make your express app easier to write, maintain and faster for development.

Within this template, NodeJS comes with three working examples of a working api called test, errorTest and saySomething, which can be viewed under src/api/api.controller.

The way this template is built makes the whole code a-lot more readable, and easier for testing.

api.controller.ts:

  @Get('/test') // This tells express to route on /api/test
  test() {
    return responses.getOkayResponse();
  }

The responses.getOkayResponse(data?: any) is just a simple method that returns a JSON response:

export function getOkayResponse(data?: any) {
  return {
    status: 'ok',
    data: data
  } as ActionResponse<any>;
}

ActionResponse objects are objects that specify a response to an action done on the server. You can provide data which comes with the response. If the status of the ActionResponse is error, it will appear as toast by default in the client.

You can test this api easily by running the express server:

npm run node

Now simply access your server in this url:

http://localhost:3000/api/test

Working with API params

Let's review the working example of saySomething:

api.controller.ts:

  @Get('/say-something') // Route on /api/say-something
  saySomething(@QueryParams('whatToSay') whatToSay: string) { // Setting the @QueryParams decorator tells express to extract the request.query['whatToSay'] into the whatToSay param.
    return responses.getOkayResponse(whatToSay);
  }

Now simple open up your browser to the api url with a 'what' param:

http://localhost:3000/api/say-something?what=Hello

And you will get this output:

{
  "status": "ok",
  "data": "Hello"
}

API middlewares

The api comes with some prepacked middlewares which can be found in the src/middlewares directory:

  • auth.middelware - Authenticates the user against the stored credentials on the database (currently based on Mongoose).
  • cors.middleware- Allows passing CORS using the config.CORS_OPTIONS.

Database

This template uses mongoose as the backend server to store users. It has only one model called UserProfileModel which you can find in the src/models directory. You can view the database code at the src/db.ts file, which basically is responible with the communication to the database.

In order to configure the database connection string, please review the Environment configurations part of this readme.

Logging using Ts.LogDebug

This template comes ready with Ts.LogDebug. By default it will save all of the error logs into the logs directory. You can edit the logging configurations in the server.ts file:

  /**
   * Returns the logger configurations.
   */
  private getLoggerConfigurations(settings: IServerSettings): Partial<ILoggerSettings> {
    // All logs are saved to the logs directory by default, you can specify custom directory in the associated configuration file ('LOGS_DIR')
    const logsDir = config.LOGS_DIR || path.join(__dirname, 'logs');

    // Add file appenders (app.log for all logs, error.log only for errors)
    $log.appenders.set('file-error-log', {
      type: 'file',
      filename: path.join(logsDir, `error.log`),
      levels: ['error']
    });

    // --> Uncomment this line if you want to log all data
    // .set('file-log', {
    //   type: 'file',
    //   filename: path.join(logsDir, `app.log`)
    // });

    return {
      ...settings.logger,
      debug: config.DEBUG_MODE,
      level: config.DEBUG_MODE ? 'debug' : 'info'
      /* --> Uncomment to add request logging
        requestFields: ['reqId', 'method', 'url', 'headers', 'body', 'query', 'params', 'duration'],
        logRequest: true
        */
    };
  }

SSL (https support)

This template comes with SSL support right out of the box. The only things you need to configure in your configuration file is the SSL_CERTIFICATE:

  SSL_CERTIFICATE: {
    KEY: string;
    CERT: string;
    CA: string;
  };

Let's say we want to configure the production to enable HTTPS, simply open up the src/config/production.json file and configure it as followed:

{
  ...
  "DB_URI": "production-mongo-uri",
  "CLIENT_URL": "http://yourwebsite.com",
  // You must create a certificate in order to enable SSL (you can use https://letsencrypt.org/ for a free certificate)
  "SSL": {
    "CA_PATH": "path/to/chain.pem",
    "PRIVATE_KEY_PATH": "path/to/privkey.pem",
    "CERTIFICATE_PATH": "path/to/cert.pem"
  }
  ...
}

Now when your server loads up, it will call this method in the server.ts file:

  /**
   * Returns the SSL (https) if any configured for this environment.
   */
  getSSLConfigurations() {
    const sslConfig = config.SSL_CERTIFICATE;

    if (!sslConfig) return {};

    return {
      httpsPort: 443,
      httpsOptions: {
        key: sslConfig.KEY,
        cert: sslConfig.CERT,
        ca: sslConfig.CA
      }
    };
  }

Authentication and roles

This template comes prepacked with JWT authentication and associated middlewares to authenticate users. in the src/auth.ts file you will be able to see how the authentication is implemented.

Basically, when a login occurs, the user is being authenticated against a hased password using bcrypt, if the passwords match, a token is being generated containing the user data within.

When accessing guarded routes (using the authenticationMiddleware in the auth.ts file), the token will be decrypted and checked to see if it's valid. If so, the request will pass and a req.user property will be filled with currently logged on user.

For example, let's take a look at a guarded route, such as the /api/profile.

TODO: Add correct information In the api.controller.ts you can see the following code:

  @Get('/profile')
  @UseBefore(AuthMiddleware)
  getProfile(@RequestUser() user: UserProfile): UserProfile {
    return user;
  }

The UseBefore decorator will call the AuthMiddleware to check if the user is authorized to login.

Simple isn't it? The token is being delivered in the Authorization header in the format of Authorization: Bearer ${Token}.

What about user roles? Each user profile has an array of roles which holds strings which contains the roles relevant for the user. For example, if you add the role admin to your user you should be able to access the /api/admin_test endpoint as it is guarded using the AuthMiddleware.

Let's see how it is implemented.

api.controller.ts:

  @Get('/admin')
  @UseBefore(AuthMiddleware, { role: 'admin' })
  adminTest() {
    return this.test();
  }

Social Authentication

The procedure of social authentication takes place in the client side, after the client obtains an access token from the 3rd party (Google, Facebook), that access token will be delieverd to the social-login/provider (replace provider with the 3rd party name), which will create a user from the token provided by accessing that specific 3rd party social network user profile information and map the user data into a data applicable for our website.

The authentication is implemented via the passport npm package with packages like passport-facebook-token and passport-google-token. If A user with the provided email exists, it is returned with a new access token which is only relevant for our app (just like normal authentication).

Take a look at the src/social-auth implementation to see how the access token is being used.

Environment configurations

This template is using the npm config package load configurations. You can read more about it here: https://www.npmjs.com/package/config

All of the configurations are located at the src/config directory. The way it loads the configuration is by first loading the default.json files and then load the associated environment configuration (by default development.json).

In order to change the environment you must specify the NODE_ENV environment variable.

For example, if you run on production specify: NODE_ENV = production.

There is a special configurations for the test environment as it starts up a test server on a different port and different credentials.

Testing (Unit Tests\API Tests)

This template comes with Mocha and Chai integrated.

There are tests for all of the following:

  • API tests
  • Tests for middlewares and services
  • General tests

Each file that has a test has a corresponding .spec file with the same name. For example, for the api tests:

/src/controllers/api.controller.spec.ts - you can find all api tests.

Test database

When the unit tests are running, they relay on a database connection, especially the API tests, as these tests write mock data to the database before running the tests.

Before running the tests, you must setup the tests database. You can do this easily using the following docker command:

docker-compose up -d test-db

This will start a clean test database on a different port then the normal database.

Running the tests

In order to run the tests, enter the following commands:

# Start the test database before running the tests
docker-compose up -d test-db

### ---> Wait for the database to run (at least 30 seconds for the first time)

# Wait for the database to run, and then run the tests
npm test

All configurations will be taken from the /src/config/test.json file, which is configured by default to connect a different port and a different user\password (test\test) in order to run the tests.

If you would like to run this in your own CI\CD tool, make sure write the following in the test run pipeline:

# Automatically sets up the database using docker-compose
export SETUP_DB=true
# Start the unit tests
npm test

This will automatically setup the test database and close it when the tests were finished.

Sharing code (models, interfaces, etc)

You can use the shared directory in order for NodeJS and Angular to share the same code to be used on both sides without the need of re-writing the models for each.

The already existing models are:

  • ActionResponse - a simple response to a user action performed on the api. The server will send this response, and the client will read it.
  • UserProfile - a simple user profile model to used for authentication.

Form validations

This template comes with class-validator built in. Which makes it a-lot more easier to write form validations. As this template shares code between Angular and NodeJS, validations will happen across both platforms.

Let's look at the UserProfile model for example:

import { Form } from './forms';
import { UserProfile } from './user-profile';
import { IsEmail, MinLength } from 'class-validator';

export class UserProfileModel implements UserProfile {
  @IsEmail()
  email: string;

  @MinLength(1)
  firstName: string;
  @MinLength(1)
  lastName: string;
  @MinLength(6)
  password: string;

  roles?: string[];
}

The decorators you see like @IsEmail, @MinLength are class-validator decorators and allows us to easily force fields to pass certain validations.

For example, when registering a user validations takes place in this way:

  • Angular - checks that all fields are valid using the FormValidatorDirective, each field on your form will automatically show if it is valid or invalid according to the validation set on it.

    The FormValidatorDirective is a directive set on a form which simply checks each input and according to it's name assigns the validations relative to it. Take a look at this example:

    angular-src/src/app/components/register/register.component.html:

      ...
      <form #form="ngForm" class="col-12 form" [appFormValidator]="userProfile" [appFormValidatorForce]="true">
          <div class="container">
            <div class="row">
              <div class="col-md-6">
                <div class="form-group">
                  <label for="email">Email</label>
                  <input type="text" class="form-control" name="email" [(ngModel)]="userProfile.email" id="email"
                    aria-describedby="helpId" placeholder="[email protected]">
                </div>
    
                <div class="form-group">
                  <label for="password">Password</label>
                  <input type="text" class="form-control" name="password" [(ngModel)]="userProfile.password" id="password"
                    aria-describedby="helpId" placeholder="Password">
                </div>
    
              </div>
        ...

    See the appFormValidator directive? it associated with the userProfile object, which is an instance of UserProfileModel. This allows you to easily Forces validations on forms and errors to the user.

  • NodeJS - on the server side validations are taken place in this way: /src/controllers/api.controller.ts:

    @Post('/register')
    register(@BodyParams() userProfile: UserProfile): Promise<UserProfile> {
      return registerForm.getHashedPassword().then(hashedPassword => {
        return UserProfileDbModel.create({
          ...registerForm,
          password: hashedPassword
        });
      });
    }

    The validation of class-validator will take place automatically using the class-validator, you can read about it here: https://tsed.io/docs/validation.html#custom-validation.

    The pipes required for class-validator to take place, are already implemented at /src/pipes;

Running on production

In order to run this code on production, you must first compile it. There a few things to take into consideration:

Running Angular and NodeJS on the same server

This template comes with Angular and NodeJS bundled together and can be up and running together on the same NodeJS server. This takes place using the build.sh bash script that knows how to compile them together and bundle them.

How does it work? Well it simply compiles each one seperatly and then copies the angular-src output dist directory into the NodeJS src directory and delievers them in the src/server.ts like this:

// Point static path to Angular 2 distribution
this.express.use(express.static(path.join(__dirname, 'dist')));

// Deliever the Angular 2 distribution
this.express.get('*', function(req, res) {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
});

Take into consideration that it will not work on debug mode.

When building your image for production it should contain the following commands:

npm run build # Call the build.sh script to start the build (it also installs the deps required if they do not exist)

And to run this code simple:

npm start

Docker\Docker-Compose

This template comes ready with Dockerfile based on node:12.18.1-alpine3.11 docker image.

It also comes with a ready out of the box docker-compose.yml file which can be used to start-up the database and the web interface.

Docker-compose

You can fire-up the database and the web interface using the following command:

# This will build web docker image automatically if it does not exist
docker-compose up -d

You can also build the web image manually like this:

docker-compose build web

The environment variable for communication using docker-compose is already included in the .env file. This .env file contains the DB_URI of the database which the web will be able to to access.

Docker image build

In order to build the docker image without docker-compose, you can simply run the following command:

docker build -t my-docker-image:0.0.0 .

And in order to run your docker on port 8080 simply run the following command:

docker run -p 8080:3000 -itd my-docker-image:0.0.0

Or you can simply use docker compose:

docker-compose up

This will run your container on port 3000.

The build script (build.sh)

The build script called build.sh is a shell script provided with the template which by default will compile the typescript NodeJS server side and Angular into one. This means when you run the server after the build you will have both on the same node container.

Make sure to include the NODE_ENV environment variable (or else the build will be set to development environment) before calling this script. The build will compile and copy all of the required configurations for the specified environment, and will generate the Angular code according to that environment.

By default, when building to production, Server Side Rendering (SSR) is set to build as well:

# TODO: Remove this 'if' statment until the 'fi' if you don't want SSR at all
if [ $ENV == "production" ]; then
    echo "Building Angular app for SSR..."
    ./node_modules/.bin/ng run angular-src:server:production
    check_errcode "Failed to build Angular app for SSR! aborting script!"
else
    echo "Skipping build for SSR as environment is NOT production"
fi

You can remove this set of code if you don't want it to take place at all.

Seperating client and server

Server as standalone

In order to run the server as standalone, simply compile it:

npm run build:node

The output will be projected into the dist directory.

Angular as standalone

In order to run angular as a standalone, simply compile it:

npm run build:angular

The output will be projected into the angular-src/dist directory.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].