Nodemi
Boilerplate for Nodejs. Handling routing, Rule validation, ORM, Media library, File request handling, Jwt auth, Role & Permissions, Resources, Locale, Mail, Seeder & more..
Install / Use
/learn @Mamena2020/NodemiREADME
Nodemi
Boilerplate for nodejs. base on express js.
-
Features
-
Model - ORM
Create model via cli and make relation between.
-
Media library
Binding media to any Model, so any model can own the media, and will able to save media, get media, and destroy media. Media can be stored to
Local storageorFirebase Storage. -
File request handling
Not worry about handling uploaded file, just upload from client side, and you can access file in request, ex:
req.body.avatar. -
Request validation
Determine if request passes the rule. You can create
custom rulevia cli. -
Role and Permissions
Binding to any model, any model can have a role and permissions, set role, checking access.
-
Resources
Create custom resource from resources.
-
Auth - JWT/Basic Auth
Create token, re generate token, and set middleware authorization for certain routes.
-
Locale
Enabled or disabled locale or just enabled on certain routes.
-
Mail
Create mail via cli, and send mail with html, file, or just text.
-
Firebase Cloud Messaging
Sending push notification from server to client device.
-
Seeder
Running seeder via cli.
-
-
Live demo
| Action | Method | Auth | Body | EndPoint | | --------------- | ------ | ------ | ---------------- | ----------------------------------------------------- | | Login | POST | | email | https://nodemi.onrender.com/api/login | | | | | password | | | | | | | | | Register | POST | | email | https://nodemi.onrender.com/api/register | | | | | name | | | | | | password | | | | | | confirm_password | | | | | | | | | Token | GET | | | https://nodemi.onrender.com/api/token | | | | | | | | | | | | | | Logout | DELETE | | | https://nodemi.onrender.com/api/logout | | | | | | | | Get User | GET | Bearer | | https://nodemi.onrender.com/api/user | | | | token | | | | | | | | | | Get Users | GET | Bearer | | https://nodemi.onrender.com/api/users | | | | token | | | | | | | | | | Forgot Password | POST | | email | https://nodemi.onrender.com/api/forgot-password | | | | | | | | Reset Password | PUT | | new_password | https://nodemi.onrender.com/api/reset-password/:token |
Getting Started
- Clone this repo
httpsorSSH
Clone and move to directory project and run npm install
git clone git@github.com:Mamena2020/nodemi.git
-
Create database
Create database mysql or pgsql.
#mysql example
mysql -u root -p
# enter your password
create database mydatabase;
#pgsql example
createdb -h localhost -p 5432 -U myPgUser mydatabase
-
Setup .env
After creating your database, you can fill in the .env file and start your code.
cp .env.example .env
Model
-
Create new model via cli.
npx nodemi make:model Product
The model will be created in the models directory.
import { Model, DataTypes } from "sequelize";
import db from "../core/database/Database.js"
class Product extends Model {}
Product.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize: db,
tableName: 'products',
modelName: 'Product',
timestamps: true
}
);
export default Product
Automatically registered in the loadModels function in the models/Models.js file.
const loadModels = async () => {
await Product.sync({
alter: true, // not recomended on production mode
})
....
Full <a target="_blank" href="https://sequelize.org/docs/v6/core-concepts/model-basics/"> documentation </a> of ORM
-
Noted
All relationships between models should be defined in the loadModels function.
When a model is removed from the models directory, it is important to also remove its corresponding relationship from the loadModels function in the models/Models.js file.
Media
Any model can own media by binding the model to the media inside the loadModels function using hasMedia(YourModel).
const loadModels = async () => {
await Product.sync({
alter: true, // not recomended on production mode
})
await hasMedia(Product)
-
Save a file
After binding model using hasMedia(YourModel), then your model will able to save a file using instance.saveMedia(file,mediaName). If the instance already has a file with the same name, then the file will be replaced with a new file.
const product = await Product.findOne({
where: {
id: 1
}
})
await product.saveMedia(req.body.file,"thumbnail") // if success then will return media object
You can save files to either Local storage or Firebase storage.
To save to Local storage, just set your .env file MEDIA_STORAGE=local , and local storage directory name MEDIA_LOCAL_STORAGE_DIR_NAME=storage.
MEDIA_STORAGE=local
MEDIA_LOCAL_STORAGE_DIR_NAME=storage
To save to Firebase storage, first create your Service Account .json on firebase <a href="https://console.firebase.google.com/">Firebase Console</a>, and download and convert to base64 string, then setup the .env file.
MEDIA_STORAGE=firebase # set to firebase
FIREBASE_STORAGE_BUCKET=gs://xxxxxx.appspot.com # your firebase storage bucket
FIREBASE_SERVICE_ACCOUNT_BASE64= # base64 string of your firebase service account .json
-
Get media
Get all media by calling instance.getMedia().
const product = await Product.findOne({
where: {
id: 1
}
})
product.getMedia() // return list of object
Get media by name, params is media name
product.getMediaByName("thumbnail") // return single object
product.getMediaByName("thumbnail").url // return single object url
Get media first media
product.getFirstMedia() // return single object
product.getFirstMedia().url // return first media url
Get media with exception, params can be string or array of string
product.getMediaExcept("thumbnail_mobile") // return list of object with exception
Get all media url,
product.getMediaUrl() // return list of media url
Get all media url with exception, params can be string or array of string
product.getMediaUrlExcept(['thumbnail_mobile']) // return list of url
Get url from media object
product.getFirstMedia().getUrl()
-
Destroy media
Destroy media by calling instance.destroyMedia(mediaName). return status deleted in boolean
const product = await Product.findOne({
where: {
id: 1
}
})
await product.destroyMedia("thumbnail")
-
Noted
All media files will be automatically deleted whenever instance of your model is deleted.
Request & Upload Files
Handling Content-Type header for
- application/json
- application/form-data
- application/x-www-form-urlencoded
Handling all upload files on POST and PUT method, and nested fields.
-
File properties
Uploaded file will have this properties.
name -> file name,
encoding -> file encoding,
type -> file mimeType,
size -> file size,
sizeUnit -> file size in bytes
extension -> file extension
tempDir -> file temporary directory
Rule Validation
-
Create Request validation via cli.
npx nodemi make:request ProductRequest
The Request will be created in the requests directory.
import RequestValidation from "../core/validation/RequestValidation.js"
class ProductRequest extends RequestValidation {
constructor(req) {
super(req).load(this)
}
/**
* Get the validation rules that apply to the request.
*
* @return object
*/
rules() {
return {
}
}
}
export default ProductRequest
-
Basic usage.
const request = new ProductRequest(req)
await request.check()
if (request.isErr
Related Skills
node-connect
346.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
