Skip to content

Build super-fast & scalable RESTful APIs in minutes.

License

Notifications You must be signed in to change notification settings

kratosbase/kratos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kratos

Build super-fast & scalable RESTful APIs in minutes. For Node.js.

npm version

MIT License

Getting started

To install run:

npm i @kratosbase/kratos@0.10.1

To spin up an application, first you need to create a resource file.

Assuming you want to create an API containing a user resource. Your file should look like this:

// resources/User.js
import { Joi } from '@kratosbase/kratos'

const commonRules = {
    username: Joi.string().trim().max(15).required(),
    picture: Joi.string().trim().required(),
    password: Joi.string().trim().required(),
    last_active: Joi.date()
}

const user = {
    schema: {
        username: { type: String, unique: true, required: true },
        picture: { type: String },
        password: { type: String, required: true },
        last_active: { type: Date, default: Date.now }
    },

    validationRules: {
        post: commonRules,
        patch: commonRules
    }
}

export default user

Now in your index.js file:

import Kratos from '@kratosbase/kratos'
import user from './resources/user.js'

const db_server = 'YOUR-DB-SERVER'

const app = new Kratos({
    port: 9000,
    db_server: db_server
})

const defaultRouter = app.router({
    users: user 
    user // this could also work but routes to /user instead of /users
}).getRoutes()

app.launch(defaultRouter)

Now run node index.js and fire up your browser/postman and make a request (POST/GET/PATCH/DELETE) request to localhost:9000/api/v1/users and you should get a response.

Depending on the request type, validation rules will be applied to match the rules in the resource file.

Features

This project is being actively developed using Stack Overflow's API design best practices

  • Focus on high performance and scalability
  • Auto-routing
  • Custom routing
  • Data validation with Joi
  • Auto-query database (for auto-routing)
  • API versioning
  • HTTP response handler
  • CORS
  • Authentication

Roadmap

  • Multiple database support (Planned)
  • Authentication (✅)
  • Custom middlewares (Planned)
  • Filtering (Planned)
  • Sorting (Planned)
  • Pagination (Planned)

Documentation

Base class initialization

example:

const app = new Kratos({
    port: 9000,
    db_server: db_server,
    cors_origins: ['http://localhost:3000'] // URLs allowed to make requests to this API
})

This class accepts a config object with the following properties:

Property Type Description Default
port int Port to serve application on Random
api_version int Major app release version 1
cors_origins mixed Origins allowed to access api ['localhost']
db_server string MongoDB connection string required
disable_auth boolean Whether to disable in-built auth or not false
show_secret boolean Determines whether to enable /show-secret GET endpoint false
jwt_secret string Set custom JWT secret random string
maintenance boolean Set maintenance mode false
unprotected_routes array Set list of routes to bypass auth []

Router class initialization

example:

const defaultRouter = app.router({
    users: user, 
}).getRoutes()

This class accepts a resources object with the following properties:

Properties Type Description Default
[dynamic value] object resource object required

**note: Whatever name you give your resource object property is the same name that will be used as the resource endpoint. So according to defaultRouter in the example above. The user resource object will be consumable via [host]:[port]/api/v[version-number]/users.

Custom routing

In a scenario when you want to interact with the database in a special way, like deleting multiple documents when a user requests to delete their account... you can make use of custom routing.

Custom resources are served at

/api/v{version-number}/custom/:resource

Custom router example

const customRouter = app.expressRouter()

customRouter.get('/delete-account', async (req, res) => {
    // Initialize a mongoose model
    const user = app.model('User').model

    const post = app.model('Post').model

    // delete user and user's posts
    ***

    // Return JSON response
    return app.respond(200, res)
})

Do note, that app.model() is a mongoose wrapper for mongoose.model. This is so you have more control over how the queries are formed.

Authentication

To enable authentication you have to set disable_auth: false or remove it completely from your config object to use the default, which is also false.

disable_auth: false also enables the /get-token GET endpoint. This allows you to be able to generate tokens for use in your application.

The id query parameter is required when making a request to /get-token. Your request should look like this: /get-token?id=[userID]. This design is intentional, so that you can identify token owner in your application.

If you want to view the default jwt secret key generated by Kratos, then set show_secret: true in your config. This will enable the /show-secret GET endpoint, where you will find the jwt secret for your perusal.

If you would like to use your own custom jwt secret, then you must set jwt_secret: [SUPER_SECRET_KEY] in your config and Kratos will automatically adapt to the changes.

  • To generate non-default role tokens, visit /get-token?role={role}... where {role} is the name of the role the token is being generated for.

  • For security reasons... after copying your token, it is recommended that you remove show_token: true from your config object to hide the token endpoint.

  • To by-pass authentication for certain routes, add unprotected_routes to config like this:

const app = new Kratos({
  port: ...,
  db_server: '...',
  unprotected_routes: ['/custom/send-code', '/appointments']
})

Authentication config example

const app = new Kratos({
    ...
    disable_auth: false // not compulsory to set this
    show_token: true
})

Restricting access to certain roles

You can restrict access to your endpoints and allow only certain roles to access them by updating your resource object validationRules to look like this:

const User = {
    ...
    validationRules: {
        get: {
            single_roles: ['user', 'admin'], // Restrict GET access to /users/:id
            roles: ['admin'] // restrict GET access to /users
        }
    }
}

Default endpoints

Property Request Types Description
/{resource} GET/POST/PATCH/DELETE Resource base endpoint
/{resource}/{id} GET/POST/PATCH/DELETE Resource single-item endpoint
/{resource}/count GET Returns data containing total count of documents in resource's collection

Philosophy

As an indie hacker, I didn't want to repeatedly write queries and routing + wanted something I could spin up quickly for any project (scalable and minimalistic) while I focus mostly on the frontend. The other frameworks I found were either too robust or had bad design patterns... that's how I ended up building this.

Kratos is built on top of the framework everyone loves... specifically for building APIs that meet the highest design standard. No compromise.

Contributing contributions welcome

Constructive contributions are always welcome!

See the Contributing Guide for ways to get started.

Security issues

If you discover a security vulnerability in Kratos, please see Security Policies and Procedures.

Support

For support, feel free to create an issue or reach out on Twitter

Acknowledgements

Authors

This project is currently being maintained by

"Buy Me A Coffee"

Releases

No releases published

Packages

No packages published