Build super-fast & scalable RESTful APIs in minutes. For Node.js.
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.
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
- Multiple database support (Planned)
- Authentication (✅)
- Custom middlewares (Planned)
- Filtering (Planned)
- Sorting (Planned)
- Pagination (Planned)
const app = new Kratos({
port: 9000,
db_server: db_server,
cors_origins: ['http://localhost:3000'] // URLs allowed to make requests to this API
})
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 | [] |
const defaultRouter = app.router({
users: user,
}).getRoutes()
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
.
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
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.
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']
})
const app = new Kratos({
...
disable_auth: false // not compulsory to set this
show_token: true
})
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
}
}
}
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 |
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.
Constructive contributions are always welcome!
See the Contributing Guide for ways to get started.
If you discover a security vulnerability in Kratos, please see Security Policies and Procedures.
For support, feel free to create an issue or reach out on Twitter
This project is currently being maintained by