Skip to content

Headless CMS with Restful Api written in Typescript that provides convenient authorization, access control lists and routes following best practices. Based on Angular and ExpressJS

License

Notifications You must be signed in to change notification settings

Netherium/api-gen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

51 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Neth-api-gen

A powerful RESTful Headless CMS written in Typescript using Express and Angular

JWT auth, Access-Control Lists (ACL), Uploads, MongoDB, Angular and Angular Material in one πŸ“¦

Lines Covered Build Status Node Version Required Built with Typescript

Made with ❀ by Netherium

Table of contents

Quick Start

  1. ⚑ Npm install globally

    $ npm i -g @netherium/api-gen
  2. πŸš€ Launch

    $ neth-api-gen
  3. πŸ’» Fill in choices

  1. πŸ™ If you generated project, navigate and install dependencies

    Server

    $ cd myproject/server
    $ npm install
    $ copy `.env.sample` to `.env` and adjust credentials
    $ npm run dev 

    Navigate to http://localhost:4000/api/auth/init to initialize app

    Client

    $ cd myproject/client
    $ npm install
    $ npm run start (or ng serve)

    Navigate to http://localhost:4200 and login with your credentials

Admin Panel Login

All resources are located in the sidenav under Resources

Admin Panel Sidenav

Features

  • Typescript Intellisense Awesomeness throughout backend and UI
  • Robust routing and middleware based on same principles of Express
  • Solid modularized admin panel with Angular and Angular Material
  • MongoDB integration
  • Fuzzy search with 'mongoose-fuzzy-searching'
  • Protected routes, ACL based with middleware, using jwt-token
  • File Upload routes and thumbnail generator
  • Test and Coverage
  • REST API Documentation via swagger-ui-express
  • Various helper files and tools, i.e. CORS integration, swagger.yaml, .env environment setup
  • Several scripts for easy development and testing

Cli Options

  1. πŸ’¨ Gimmie my API!!!

    • neth-api-gen
    • Select app
    • Add entities according to your needs
    • Get a production ready(:crossed_fingers:) api + admin panel including basic routes + the entities you've added (ACL required)
    • Impress your team!
  2. πŸ’‘ I forgot to add...

    • neth-api-gen
    • Select entities
    • Add more entities to your existing neth-api-gen project, or a solid boilerplate for an ExpressJs/Angular project (modifications may apply)
    • Go and play!
  3. πŸ•ΉοΈ I want more control and faster!!!

    • neth-api-gen -i mysample.json
    • Import all the options from a json file, instead of a UI
    • Do it once, do it many!
  4. πŸ˜• But where is that JSON???

    • neth-api-gen -s
    • Oh yeah, forgot to mention it
  5. ❓ Can you help???

    • neth-api-gen -h
    • I can

⚠️ When generateApp: true, swaggerDocs is irrelevant, but you need to provide swaggerPath: "myproject/swagger.yaml"

Develop

  1. πŸ™ If you generated project, navigate and install dependencies

    Server

    $ cd myproject/server
    $ npm install

    Client

    $ cd myproject/client
    $ npm install
  2. 🌲 Setup your environment files:

    Server .env, .env.test, .env.production, according to .env.sample (under myproject/server)

    ADDRESS=localhost
    PORT=4000
    MONGODB_URL=mongodb://localhost:27017/YOUDBNAMEHERE
    SECRET=YOURSECRETHERE
    ...

    Client environment.ts, environment.prod.ts (under myproject/client/environments)

    apiUrl: 'http://localhost:4000/api',         // Endpoint of the server
    authorizedRole: ['Admin']                    // Roles that have authorized access to admin panel
    ...
  3. πŸ’¨ Develop

    Server

    $ npm run dev

    Client

    $ npm run start (ng serve)
  4. πŸ’‘ Initialize: Navigate to http://localhost:4000/api/auth/init

    • 2 Roles will be created, 1 Admin, 1 Public
    • 1 User will be created, based on your .env credentials
    • Resource permissions will be created for basic routes, with default access to admin Role
  5. πŸš€ Build!

    Server

    $ npm run build

    Client

    $ npm run build
  6. πŸŽ†Your build is ready to deploy !πŸŽ†

Basic Routes

The basic routes provided are listed below. Each one of them is being reflected by its own route, controller, model

Auth

  • πŸ”“ api/auth/register [POST]
  • πŸ”“ api/auth/login [POST]
  • πŸ” api/auth/profile [GET, PUT, DELETE]
  • πŸ”“ api/auth/init [GET]

Roles

  • πŸ” api/roles [GET, GET /:id, POST, PUT /:id, DELETE /:id]

Resource-Permissions

  • πŸ” api/resource-permissions [GET, GET /:id, POST, PUT /:id, DELETE /:id]

Users

  • πŸ” api/users [GET, GET /:id, POST, PUT /:id, DELETE /:id]

Media-Objects

  • πŸ” api/media-objects [GET, GET /:id, POST, PUT /:id, DELETE /:id]

Docs

  • πŸ”“ api/docs [GET]

Root

  • πŸ”“ / [GET]

Endpoints

  • πŸ” api/endpoints [GET]

Books (Provided example Resource Route)

  • πŸ” api/books [GET, GET /:id, POST, PUT /:id, DELETE /:id]

Resource Permissions

  • Add a new route with Access-Control List (ACL) by invoking middleware function Auth.getACL() I.e. file article.route.ts
    export class ArticleRoute {
      constructor() {
        this.router.get('/', Auth.getAcl(), controller.list);
        ...
        this.router.post('/', Auth.getAcl(), controller.create);
      }
    }
  • Add the appropriate resource-permission for this resource for each method (list, create, in this case) and for each method the roles that will have access to.
POST api/resource-permissions
{
    resourceName: 'articles',
    methods: [
        {
            name: 'list',
            roles: [PublicRoleId]
        },
        {
            name: 'create',
            roles: [AdminRoleId, RegisteredUserRoleId]
        }
    ]
}

⚠️ If you add at least 1 unauthenticated role then this resource route will be open

Coding Tips

Get Service

  • Register any service in server.ts, under registerServices function
  • Access it anywhere by destructuring it const {uploadService} = req.app.get('services');

Get Authenticated User

  • When a route is authenticated, you can access the authenticated user by res.locals.authUser

Get Resource Permissions

  • For optimization, resource-permissions are stored in app.locals.resourcePermissions. If you update manually a resource (i.e. not via api call, but database manipulation), restart server or call Auth.updateAppPermissions()

Structure

Follow the structure below. It will keep things and your mind tidy 🌼

Server
.
β”œβ”€β”€ dist                # Compiled files ready to deploy `npm run build`
β”œβ”€β”€ uploads             # When using local provider this is where uploads go
β”‚
β”œβ”€β”€ src                 # Your code goes here
β”‚   β”œβ”€β”€ routes          # Routes that define endpoints, methods, handlers and middleware
β”‚   β”œβ”€β”€ controllers     # Controllers that handle functionality from routes
β”‚   β”œβ”€β”€ models          # Mongoose models and typescript interfaces
β”‚   β”œβ”€β”€ middleware      # Middleware functions
β”‚   β”œβ”€β”€ services        # Services in OOP style that can be called in controllers 
β”‚   β”œβ”€β”€ helpers         # Exported functions that need no instantiation  
β”‚   └── server.ts       # Server entrypoint file
β”‚                       
β”œβ”€β”€ test                # Automated tests `npm run test`
β”‚
β”œβ”€β”€ swagger.yaml        # Swagger documentation (`api/docs`) defined in yaml format
β”œβ”€β”€ LICENSE             # License file
└── README.md

Client
.
β”œβ”€β”€ dist                            # Compiled files ready to deploy `npm run build`
β”‚
β”œβ”€β”€ src                             # Your code goes here
β”‚   β”œβ”€β”€ app             
β”‚   β”‚   β”œβ”€β”€ components              # Shared components throughout the Angular app
β”‚   β”‚   β”œβ”€β”€ models                  # Shared models throughout the Angular app    
β”‚   β”‚   β”œβ”€β”€ services                # Shared core services throughout the Angular app
β”‚   β”‚   β”œβ”€β”€ dialogs                 # Shared dialogs
β”‚   β”‚   β”œβ”€β”€ modules                 # Lazy loaded modules, each generated resource corresponds to 1 module
β”‚   β”‚   └── app-routing.module.ts   # Routing module that binds all lazy loaded modules, each generated resource has a child under `childrenRoutes`  
β”‚   β”œβ”€β”€ assets                      # Static resources
β”‚   β”œβ”€β”€ environments                # Angular environment configuration
β”‚   β”œβ”€β”€ theming                     # Angular Material Theming Styles
β”‚                      
... Rest Default Angular Structure

Uploads

  • Uploads can be stored locally or remotely, see .env
  • To upload a file POST api/uploads with Content-Type: multipart/form-data; or use Postman
  • Field file is the file data, altenativeText, caption are optional strings
  • PUT api/uploads/:id accepts Content-Type: application/json; as only altenativeText, caption can be modified
  • If file of image type, a thumbnail (80x80) will be generated

Under The Hood

  • When you generate an App

  • When you generate an Entity, multiple files are generated under server and client folders Server

    • Controller, Model, Route files are generated under their corresponding folders ./server/src/controllers/entity.controller.ts, ./server/src/models/entity.model.ts, ./server/src/routes/entity.route.ts
    • An entry in server.ts is created, under method routes

    Client

    • A module is created under its corresponding folder ./client/src/app/modules/entityfolder/...
    • An entry in app-routing.module.ts is created, under variable childrenRoutes

Tests

  • Server testing based on Mocha, chai and chai-http
  • Client testing based on the default Angular test tools Jasmine (Tests not provided/generated for Angular, but you can follow standard Angular practices)

Run tests

Server

$ cd myproject/server
$ npm test

Client

$ cd myproject/client
$ npm test (or ng test)

Coverage

Server Coverage is based on nyc

Run coverage (generated under folder coverage)

$ npm run test:coverage

Debug

To debug TS without compiling it, you can setup your IDE of choice as in the example below
Note: Running older versions of node may require attaching --inspect before --require

Authors

Netherium

Copyright and license

Code released under the MIT license

About

Headless CMS with Restful Api written in Typescript that provides convenient authorization, access control lists and routes following best practices. Based on Angular and ExpressJS

Resources

License

Stars

Watchers

Forks

Packages

No packages published