Beech API
is a Node.js framework it's help you with very easy create API project under Node.js
Beech API
is a Very easy for using, very feather framework, easy to installation, easy to implementation, and high security.
Node.js
>= 14.19.0+ (recommended)
Beech API requires Node.js version 14.19.0 or above. You can manage multiple versions of Node on the same machine with nvm or nvm-windows. So, Let's go to install beech-api
# NPM
$ npm install beech-api --global
# Yarn
$ yarn global add beech-api
Installation demo:
After installation, you will have access to the beech-app
binary in your command line.
You can check you have the right version with this command:
$ beech-app --version
Create a new project run:
$ beech-app create hello-world
Run your project:
$ cd hello-world
$ npm start
# OR
$ yarn start
โ Note: The Beech API it's start server at http://localhost:9000 you can change new a port in app.config.js
file.
The Beech API upgrade to latest version command avariable :
// Project upgrade
$ beech-app update
// Global upgrade
$ beech-app update -g, --global
After installation, you will have access to the beech
binary in your command line.
The beech
command has a number of options and you can explore them all by running:
$ beech --help
The beech
command line available:
Usage:
$ beech [options] [arguments] [special]
Options:
?, -h, --help Display this help message.
-v, --version Display the application version.
The following commands are available:
$ beech make <endpoint> Create a new Endpoints and unit test file,
You might using [special] `-R, --require`
for choose Model(s) used to endpoint file.
$ beech make <model> -M, --model Create a new Models file.
$ beech make <helper> --helper Create a new Helpers file.
$ beech passport init Initialize authentication with passport-jwt.
$ beech skd init Initialize Job Scheduler file.
$ beech key:generate, key:gen Re-Generate application key (Dangerous!).
$ beech hash:<text> Hash text for Access to Database connection.
โ Note: Every to create new project will be generated new app_key
in app.config.js
file, If you can re-generate. Can use command $ beech key:generate
or $ beech key:gen
You might connection to Database with database_config
object in app.config.js
file. Anything can support to multiple Database connections.
The connection base on pool_base
in global.config.js
file.
basic
= Support only Raw Query with Only MySQL.sequelize
= Support PDO, Raw Query with various Database Engine.
In case Access to Database must to Hash the username
and password
with Beech CLI like this.
// Hash database username
$ beech hash:root
Output: m42BVxQ6Q4kLdRX7xS_Hm7WbQiNqShJDvw9SLCgI431oafWBtQJoJDnoCL
// Hash database password
$ beech hash:password
Output: FjgcgJPylkV7EeQJjea_EeifPwaHVO9onD3ATk3YYAyvjtMGu3dcDS0ejA
For Example:
๐ app.config.js
// basic & sequelize (needed Hash)
...
database_config: [
{
dialect: "mysql",
name: "mysql_my_store_db",
host: "localhost",
username: "m42BVxQ6Q4kLdRX7xS_Hm7WbQiNqShJDvw9SLCgI431oafWBtQJoJDnoCL",
password: "FjgcgJPylkV7EeQJjea_EeifPwaHVO9onD3ATk3YYAyvjtMGu3dcDS0ejA",
database: "my_store_db",
port: "3306",
is_connect: true, // boolean, Turn ON/OFF to connect
},
...
],
...
โ Caution! : Every re-new generate app_key
. Must to new Hash your Access and change to ALL Database connections.
The endpoints
keep the endpoints basic request files currently support GET
, POST
, PUT
, PATCH
and DELETE
.
So, you might create new endpoints with constant endpoint
object variable in src/endpoints/
folder and file neme must be end with -endpoints.js
$ beech make endpointName
You might using [special] -R, --require
for choose Model(s) used for that endpoint.
๐ fruit-endpoints.js
exports.init = () => {
// GET method
endpoint.get("/fruit", Credentials, (req, res) => {
// @response
res.json({
code: 200,
status: "SUCCESS",
message: "GET /fruit request.",
});
});
// POST method
endpoint.post("/fruit", Credentials, (req, res) => {
// @response
res.json({
code: 200,
status: "SUCCESS",
message: "POST request at /fruit",
result: {
id: req.body.id,
name: req.body.name,
},
});
});
// PUT method
endpoint.put("/fruit/:id", Credentials, (req, res) => {
// @response
res.json({
code: 200,
status: "SUCCESS",
message: "PUT request at /fruit/" + req.params.id,
});
});
// DELETE method
endpoint.delete("/fruit/:id", Credentials, (req, res) => {
// @response
res.json({
code: 200,
status: "SUCCESS",
message: "DELETE request at /fruit/" + req.params.id,
});
});
...
}
๐ fruit-endpoints.js
// Require Model schema, Function & Others
const { Fruit } = require("@/models/Fruit");
exports.init = () => {
// GET method
endpoint.get('/fruit', async (req, res) => {
// example call Fruit model for get data
res.json({
code: 200,
status: "SUCCESS",
results: await Fruit.findAll();
});
});
...
}
The models
keep the files of function(s) data managemnets for Retriving, Creating, Updating and Destroying (CRUD). for understanding you might make model name same your table name inside src/models
folder.
$ beech make modelName --model
๐ Fruit.js
module.exports = {
// Example basic function get data
getData() {
return {
id: 1,
name: "John Doe",
}
},
// Example basic function get data from MySQL table
getFruit() {
// calling Pool connection name by `mysql.default_db`
mysql.default_db.query("SELECT * FROM fruit", (err, results) => {
if (err) { throw err }
return results;
});
}
};
You can asign more DataTypes, Learn more : Sequelize docs
๐Fruit.js
const { Schema } = require("beech-api");
// Define table Schema with `Schema(sql.default_db)` connection name
const Fruit = Schema(sql.default_db).define("fruit", {
fruit_id: {
field: "id", // Rename PK field to fruit_id Ref: `id` field in fruit table
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
fruitName: DataTypes.STRING,
fruitQty: DataTypes.INTEGER,
fruitPrice: {
type: DataTypes.INTEGER,
allowNull: false, // Allow null feilds
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
});
Users.options = {
// Allow magic generate default endpoint (CRUD)
defaultEndpoint: true, // boolean DEFAULT: true ๐ // It's like magic creating The endpoints for you (CRUD) โจ
limitRows: 100, // Limit rows default 100
};
// Example Finder by id (ORM), Learn more: https://sequelize.org/docs/v6/core-concepts/model-querying-finders/
function exampleFindOneFruitById(id) {
return Fruit.findOne({ where: { id: id } });
}
// Example Raw Query, Learn more: https://sequelize.org/docs/v6/core-concepts/raw-queries/
function exampleGetAllFruit(id) {
return Fruit.query("SELECT * FROM fruit");
}
// Example Raw Query with Model Instances. This allows you to easily map a query to a predefined model
function exampleGetAllFruitWithModelInstance(id) {
return Fruit.query("SELECT * FROM fruit", {
model: Fruit, // When JOIN table needed register that table [Fruit, ...]
mapToModel: true // pass true here if you have any mapped fields
});
}
...
// Export Schema, Function, ...
module.exports = {
Fruit,
exampleFindFruitById,
exampleGetAllFruit,
exampleGetAllFruitWithModelInstance,
...
};
Now! you can request to /fruit
with methods GET, POST, PATCH and DELETE like this.
Efficacy | Method | Endpoint | Body |
---|---|---|---|
Create | POST | /fruit | { } |
Read | GET | /fruit | No |
Read | GET | /fruit/:id | No |
Read | GET | /fruit/:limit/:offset | No |
Read | GET | /fruit?someField=1 | No |
Update | PATCH | /fruit/:id | { } |
Delete | DELETE | /fruit/:id | No |
For Example to Add some Basic Conditions with QUERY STRING
into GET /fruit?someField=[eq,1]
Endpoint.
GET: /fruit?isActived=[eq,1] // isActived = 1
GET: /fruit?fruitName=[like,Banana%] // fruitName LIKE 'Banana%'
GET: /fruit?cost=[gt,50]&qty=[lt,10] // cost > 50 AND qty < 10
GET: /fruit/10/0?qty=[lt,10] // qty < 10 LIMIT 0,10
For usage avariable:
// Basics
[eq, 3] // = 3
[ne, 20] // != 20
[is, null] // IS NULL
[not, null] // IS NOT NULL
[or, [5, 6]] // (someField = 5) OR (someField = 6) // Not support NULL value
// Number comparisons
[gt, 6] // > 6
[gte, 6] // >= 6
[lt, 10] // < 10
[lte, 10] // <= 10
[between, [6, 10]] // BETWEEN 6 AND 10
[notBetween, [11, 15]] // NOT BETWEEN 11 AND 15
// Other operators
[in, [1, 2, 3]], // IN [1, 2, 3]
[notIn, [1, 2, 3]], // NOT IN [1, 2, 3]
[like, %hat] // LIKE '%hat'
[notLike, %hat] // NOT LIKE '%hat'
[startsWith, hat] // LIKE 'hat%'
[endsWith, hat] // LIKE '%hat'
[substring, hat] // LIKE '%hat%'
Sequelize does not use transactions by default. However, for production-ready usage of Sequelize, you should definitely configure Sequelize to use transactions.
Beech use Sequelize supports three ways of using transactions:
// First, we start a transaction from your connection and save it into a variable
const t = await Fruit.transaction();
try {
// Then, we do some calls passing this transaction as an option:
const fruit = await Fruit.create({ fruitName: 'Banana', fruitQty: '5', }, { transaction: t });
await fruit.addSibling({ fruitName: 'Litle', fruitQty: '2', }, { transaction: t }); // Error function
// If the execution reaches this line, no errors were thrown.
// We commit the transaction.
await t.commit();
} catch (error) {
// If the execution reaches this line, an error was thrown.
// We rollback the transaction.
await t.rollback();
}
// First, we start a transaction from your connection and save it into a variable
Fruit.transaction(async t => {
try {
// Then, we do some calls passing this transaction as an option:
const fruit = await Fruit.create({ fruitName: 'Banana', fruitQty: '5', }, { transaction: t });
await fruit.addSibling({ fruitName: 'Litle', fruitQty: '2', }, { transaction: t }); // Error function
// If the execution reaches this line, no errors were thrown.
// We commit the transaction.
await t.commit();
} catch (error) {
// If the execution reaches this line, an error was thrown.
// We rollback the transaction.
await t.rollback();
}
});
The possible isolations levels to use when starting a transaction:
const { Transaction } = require('sequelize');
// First, we start a transaction from your connection and save it into a variable
Fruit.transaction(
{
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE,
},
async t => {
try {
// Then, we do some calls passing this transaction as an option:
const fruit = await Fruit.create({ fruitName: 'Banana', fruitQty: '5', }, { transaction: t });
await fruit.addSibling({ fruitName: 'Litle', fruitQty: '2', }, { transaction: t }); // Error function
// If the execution reaches this line, no errors were thrown.
// We commit the transaction.
await t.commit();
} catch (error) {
// If the execution reaches this line, an error was thrown.
// We rollback the transaction.
await t.rollback();
}
});
The helpers
keep the files of functions for process specific something in the project. So, you might create the helpers
in path src/helpers
folder.
$ beech make helperName --helper
For Example: Text editor helper.
๐ TextEditor.js
module.exports = {
textUpperCase(text) {
return text.toUpperCase();
},
textTrim(text) {
return text.trim();
},
...
};
Passport is authentication middleware for Node. It is designed to serve a singular purpose: authenticate requests. When writing modules, encapsulation is a virtue, so Passport delegates all other functionality to the application. This separation of concerns keeps code clean and maintainable, and makes Passport extremely easy to integrate into an application.
$ beech passport init
After passport initialized the passport.config.js
it's appeared
๐ passport.config.js
module.exports = {
// Allow for using passport-jwt
jwt_allow: true,
// custom authenticaiton endpoint name, default `/authentication`
auth_endpoint: "",
// your jwt secret key
secret: "your_jwt_secret",
// token expiry time (seconds), default 86400 sec. it's expired in 24 hr.
token_expired: 86400,
model: {
// Main sql connection name. You must make sure connection name like inside `app.config.js` file and choose one connection name.
name: "default_db",
// table name of users store, default table `users`
table: "",
// secret user store field for authenticate, default field `username` and `password`
username_field: "",
password_field: "",
// JWT playload data, You can add it. Example: ["name", "email", ...]
fields: [],
// Other fields add for authentication.
guard: {
// Basic guard field, Example: ["pin", "hint", "2fa"]
guard_field: [],
// Advanced guard jwt request (needed some logical from front-end)
advanced_guard: {
allow: false,
entity: "", // default entity `timing`
secret: "top_secret",
time_expired: {
minutes: 1, // should length [0-60]
seconds: 0, // should length [0-60]
},
},
},
},
// Allow for using request with app_key entity (Every request must be using the app_key entity in headers)
app_key_allow: false
...
};
Authentication structure : Simple users
table:
==============================================================
| id | username | password | name | email |
--------------------------------------------------------------
| 1 | bombkiml | secret | bombkiml NC. | [email protected] |
| 2 | johnson | secret | johnson BA. | [email protected] |
When you config passport with users
table already. You will got Auth endpoint in available.
POST: "/authentication" // Request token
POST: "/authentication/create" // Create new Auth data
PATCH: "/authentication/update/:id" // Update old Auth data (needed id)
XHR Example :
// Request with body for gether Token
POST: "/authentication"
{
username: "bombkiml",
password: "secret"
}
// Request with body for Create Auth data
POST: "/authentication/create"
{
username: "add_new_username",
password: "add_new_secret",
name: "add_new_my_name",
email: "add_new_email"
}
// Request with body for Update Auth data
PATCH: "/authentication/update/1"
headers: Authorization: Bearer <your_token>
{
username: "update_bombkiml",
password: "update_secret",
name: "update_my_name",
email: "[email protected]"
}
You can easy using 2 Factor authenticate with guard_field
inside passport.config.js
file and add your Guard field ex: 2fa
field for Authenticate Conditions.
๐ passport.config.js
module.exports = {
...
guard: {
// Other fields add for authenticate, exmaple ["pin", "hint", "2fa"]
guard_field: ["2fa"], ๐ // your feild guard. (Disabled to remove it.)
...
},
...
}
Advance Guard for Protection your Endpoint with Timing. You can allow in object advance_guard
inside passport.config.js
file. So let's go add your Advance Guard Configuration.
๐ passport.config.js
module.exports = {
...
guard: {
...
// Advanced guard to Request (Needed some logical from front-end)
advanced_guard: {
allow: false, ๐ // advanced guard allow for All Endpoint.
entity: "", // default entity `timing`
secret: "your_advance_guard_secret",
time_expired: {
minutes: 1, // should length [0-60]
seconds: 0, // should length [0-60]
},
},
},
...
}
After configure, You must add some logic in your front-end like this.
Before add logic, We needed beech-auth0
and moment.js
for apply in Policy.
# NPM
$ npm install --save beech-auth0 moment
# Yarn
$ yarn add beech-auth0 moment
Now! you can add some logic.
const { Auth0 } = require("beech-auth0");
const moment = require("moment");
// Get UNIX TIME with moment
let unix_time = moment().unix();
// Auth0 Policy.
Auth0(unix_time, 'your_advance_guard_secret', (error, hashing) => {
// Your XHR request for All Endpoint.
POST: "/authentication"
headers: timing: hashing, ๐ // Assign advance guard entity to headers with callback hashing.
});
You can easy management users
data with Beech, Only Store, Update
NO Delete
, Anything you can make DELETE endpoint by yourself
const { Store, Update } = require("beech-api");
- Store users data with
Store()
// prepare data for store users
var data = {
username: "bombkiml",
password: "secret",
name: "bombkiml nc.",
email: "[email protected]"
}
Store(data, (err, stored) => {
if (err) throw err;
// response affected data
console.log(stored.insertId, stored.affectedRows);
});
- Update users data with
Update()
// prepare data for update users
var data = {
password: "new_secret",
name: "bombkiml NC.",
email: "[email protected]"
}
Update(data, id, (err, updated) => {
if (err) throw err;
// response affected data
console.log(updated.updateId, updated.affectedRows);
});
Latest supported with Google
and Facebook
Strategy.
The Google OAuth 2.0 authentication strategy authenticates users using a Google account and OAuth 2.0 tokens. The strategy requires a verify callback, which accepts these credentials and calls done providing a user, as well as options specifying a client ID, client secret, and callback URL.
Before your application can make use of Sign In With Google, you must register your app with Google. This can be done in the APIs & Services page of the Google Cloud Platform console. Once registered, your app will be issued a client ID and secret which will be used in the strategy configuration.
Go to open file passport.config.js
and go to google strategy
then turn allow Google Strategy is allow: true
something like this.
๐ passport.config.js
...
strategy: {
google: {
// Allow for using google strategy
allow: true,
// Authen profile store fields available: `google_id`, `name`, `email`, `photos`, `locate`
local_profile_fields: {
google_id: "google_id", // Google ID field, default field name: `google_id`
name: "your_name_field",
email: "your_email_field",
photos: "your_profile_url_field",
locate: "" // If you not store set to null or remove it.
},
// Google development Credentials OAuth 2.0 Client IDs
client_id: "GOOGLE_CLIENT_ID",
client_secret: "GOOGLE_CLIENT_SECRET",
// Callback endpoint default `/google/callback`
callbackURL: "",
// Failure redirect to your route
failureRedirect: "/login"
}
}
...
The above code is a configures and registers the Google Strategy.
allow
: Turn on/off the Google Strategy config type ofboolean
switch bytrue/false
.google_id
: Local Google ID field for store Google ID in my local database default field isgoogle_id
.local_profile_fields
: Local Profile fields for store Google user details.client_id
andclient_secret
: The options to the Google Strategy constructor must include aclientID
andclientSecret
, the values of which are set to the client ID and secret that were obtained when registering your application.callbackURL
: When registering your application. A callbackURL must also be included. Google will redirect users to this location after they have authenticated.failureRedirect
: When registering your application somthing failure it's redirect to that.
Place a button on the application's login page, prompting the user to sign in with Google.
<a href="/authentication/google" class="button">Sign in with Google</a>
โ Note: The URL "/authentication
" will be follow by auth_endpoint
when you custom it.
Facebook Login allows users to sign in using their Facebook account. Support for Faceboook Login is provided by the passport-facebook
package.
Before your application can make use of Facebook Login, you must register your app with Facebook. This can be done in the App dashboard at Facebook for Developers. Once registered, your app will be issued an app ID and secret which will be used in the strategy configuration.
Go to open file passport.config.js
and go to facebook strategy
then turn allow Facebook Strategy is allow: true
something like this.
๐ passport.config.js
...
strategy: {
facebook: {
// Allow for using facebook strategy
allow: true,
// Authen profile store fields available: `facebook_id`, `name`, `email`, `photos`, `locate`
local_profile_fields: {
facebook_id: "facebook_id", // Facebook ID field, default field name: `facebook_id`
name: "your_name_field",
email: "your_email_field",
photos: "your_profile_url_field",
locate: "" // If you not store set to null or remove it.
},
// Facebook development Credentials OAuth 2.0
app_id: "FACEBOOK_APP_ID",
app_secret: "FACEBOOK_APP_SECRET",
// You can allow Permissions facebook profile fields. Learn more (https://developers.facebook.com/docs/graph-api/reference/v13.0/user#readperms)
// **Update 2024, Now! Facebook requests permission for show Email. Learn more (https://developers.facebook.com/docs/permissions)
profileFieldsAllow: [ 'id', 'displayName', 'name', 'photos', 'email', 'location' ], // Default allowed
// Callback endpoint default `/facebook/callback`
callbackURL: "",
// Failure redirect to your route
failureRedirect: "/login"
}
}
...
The above code is a configures and registers the Facebook Strategy.
allow
: Turn on/off the Facebook Strategy config type ofboolean
switch bytrue/false
.facebook_id
: Local Facebook ID field for store Facebook ID in my local database default field isfacebook_id
.local_profile_fields
: Local Profile fields for store Facebook user details.app_id
andapp_secret
: The options to the Facebook Strategy must include an app ID and secret. you must register your app with Facebook. This can be done in the App dashboard at Facebook for Developers. Once registered, your app will be issued anapp ID
andsecret
which will be used in the strategy configuration.profileFieldsAllow
: Permissions with Facebook Login. You must allow Permissions facebook profile fields: see more (https://developers.facebook.com/docs/graph-api/reference/v13.0/user#readperms)callbackURL
: When registering your application. A callbackURL must also be included. Facebook will redirect users to this location after they have authenticated.failureRedirect
: When registering your application somthing failure it's redirect to that.
Place a button on the application's login page, prompting the user to sign in with Facebook.
<a href="/authentication/facebook" class="button">Log In With Facebook</a>
โ Note: The URL "/authentication
" will be follow by auth_endpoint
when you custom it.
The origin array to the callback can be any value allowed for the origin option of the middleware. Certain CORS requests are considered complex
and require an initial OPTIONS request (called the pre-flight request
). You can allowed CORS origin inside file beech.config.js
๐ beech.config.js
module.exports = {
defineConfig: {
// Base public path when served in development or production.
base: process.env.NODE_ENV === "production"
? "/my-api/" // For Production
: "/", // For Development
server: {
// Client request allow origin whitelist
origin: ["http://example.com", "http://my-webapp:8080", "https://cat.io"],
originSensitive: false, // Sensitive with contrasts wording
// API Request rate limit (Disabled for Remove it.)
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
limit: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
// store: ... , // Redis, Memcached, etc.
// See more: https://www.npmjs.com/package/express-rate-limit#Configuration
},
// API Duplicate Request (Disabled for Set expiration to 0 zero.)
duplicateRequest: {
expiration: 500, // Can't duplicate request for 5 milliseconds each IP requests per `window`
},
},
},
}
โ Note: When you must to allowed all Origin. You can assign *
or []
null value to origin
variable.
When you need assign specific request Endpoint with express-rate-limit, You can managemnet with Beech object rateLimit
for your custom Rate Limit like this.
const { rateLimit } = require("beech-api").Express;
// Specific of your rate limit
const specificRateLimit1 = rateLimit({
windowMs: 5 * 60 * 1000, // 5 minutes
limit: 20,
// more...
});
// Your Endpoints...
endpoint.get("/banana", specificRateLimit1, (req, res) => {
...
});
...
DON'T DO IT. ย Because it's annoying to users.
When you need assign specific request Endpoint with express-slow-down, You can managemnet with Beech object slowDown
for your custom Slow Down like this.
const { slowDown } = require("beech-api").Express;
// Specific of your slow down
const specificSlowDown1 = slowDown({
windowMs: 15 * 60 * 1000, // 15 minutes
delayAfter: 5, // Allow 5 requests per 15 minutes.
delayMs: (hits) => hits * 100, // Add 100 ms of delay to every request after the 5th one.
// more...
/**
* So:
*
* - requests 1-5 are not delayed.
* - request 6 is delayed by 600ms
* - request 7 is delayed by 700ms
* - request 8 is delayed by 800ms
*
* and so on. After 15 minutes, the delay is reset to 0.
*/
});
// Your Endpoints...
endpoint.get("/banana", specificSlowDown1, (req, res) => {
...
});
...
This middleware to Limit each IP duplicated requests per window.
When you need assign specific request Endpoint with duplicate request use express-duplicate-request, You can managemnet with Beech object duplicateRequest
for your custom Duplicate Request like this.
const { duplicateRequest } = require("beech-api").Express;
// Specific of your duplicate request
const specificDup1 = duplicateRequest({
expiration: 500, // Can't duplicate request for 5 milliseconds, Should 0 to disabled
// more...
});
// Your Endpoints...
endpoint.get("/banana", specificDup1, (req, res) => {
...
});
...
Just like you use Git / SVN to manage changes in your source code, you can use migrations to keep track of changes to the database. With migrations you can transfer your existing database into another state and vice versa: Those state transitions are saved in migration files, which describe how to get to the new state and how to revert the changes in order to get back to the old state.
You will need Sequelize CLI. The CLI ships support for migrations and project.
To create an empty project you will need to execute init
command
$ npx sequelize-cli init
This will create following folders inside databases
folder.
config
, contains config file, which tells CLI how to connect with database.models
, contains all models for your project.migrations
, contains all migration files.seeders
, contains all seed files.
Before continuing further we will need to tell CLI how to connect to database. To do that let's open default config file databases/config/database.json
It looks something like this:
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
โ Note: The database connect default port 3306 if you another port you can add object port
in config.
โ Note: If your database doesn't exists yet, you can just call npx sequelize-cli db:create
command. With proper access it will create that database for you.
Create model
use model:generate
command. This command requires two options.
--name
, Name of the model--attributes
, List of model attributes
Let's create a model name example User
. See more about of Datatypes
$ npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string,birhday:date
Until this step, we haven't inserted anything into the database. We have just created required model and migration files for our first model User.
-
Migrate Up : you can create that table in database you need to run db:migrate command.
$ npx sequelize-cli db:migrate
-
Migrate Down : you can use
db:migrate:undo
, this command will revert most recent migration.$ npx sequelize-cli db:migrate:undo
To manage all data migrations you can use seeders. Seed files are some change in data that can be used to populate database table with sample data or test data.
Let's create a seed file which will add a demo user to our User table.
$ npx sequelize-cli seed:generate --name user
In last step you have create a seed file. It's still not committed to database. To do that we need to run a simple command.
-
Seed Up : you can execute that seed file and you will have a user inserted into
User
table.$ npx sequelize-cli db:seed:all
-
Seed Down : seeders can be undone if they are using any storage. There are two commands available for that:
If you wish to undo most recent seed
$ npx sequelize-cli db:seed:undo
If you wish to undo a specific seed
$ npx sequelize-cli db:seed:undo --seed <seederName>
If you wish to undo all seeds
$ npx sequelize-cli db:seed:undo:all
Test using Jest for testing the project. Jest is a delightful JavaScript Testing Framework with a focus on simplicity. Learn more Jest docs
So, When you make the new endpoints it's automatic create test file end with .spec.js
in __test__
folder with constant baseUrl
variable and axios
package.
For Example endpoints testing :
๐ fruit-endpoints.spec.js
const endpoint = baseUrl.concat("/fruit");
describe("Test endpoint : " + endpoint, () => {
it("Truthy!", () => {
expect("/fruit").toBeTruthy();
});
it("Respond with basic GET status code 200", (done) => {
axios.get(endpoint).then((res) => {
expect(200).toEqual(res.data.code);
done();
});
});
});
# Implement with PM2
PM2 is a daemon process manager that will help you manage and keep your application online. Getting started with PM2 is straightforward, it is offered as a simple and intuitive CLI, installable via NPM.
# Start service as standalone
$ pm2 start ./node_modules/beech-api/packages/cli/beech --name <serviceName>
# OR
# Start service as cluster mode
$ pm2 start ./node_modules/beech-api/packages/cli/beech --name <serviceName> -i <instances>
# Implement with Docker
Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly.
Docker builds images automatically by reading the instructions from a Dockerfile -- a text file that contains all commands, in order, needed to build a given image. A Dockerfile adheres to a specific format and set of instructions which you can find at Dockerfile reference.
๐ Dockerfile
FROM node:14.19-alpine
ENV NODE_ENV=production
WORKDIR /usr/src/api
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent && mv node_modules .
COPY . .
EXPOSE 9000
CMD ["node", "./node_modules/beech-api/packages/cli/beech"]
The docker build command builds an image from a Dockerfile and a context. The buildโs context is the set of files at a specified location PATH
or URL
. The PATH is a directory on your local filesystem. The URL is a Git repository location.
$ docker build -t <imageName> .
โ Note: You can specify a repository and tag at which to save the new image : $ docker build -t <imageName>:<tags> .
-
After create
image
you can run docker engine following :$ docker run -d -p 9000:9000 --name <containerName> <imageName>
# Initiate swarm $ docker swarm init # Run docker service $ docker service create --replicas <instances> --name <containerName> --publish 9000:9000 <imageName>
Want to contribute or join for great job!, You can contact to me via
- GitHub: bombkiml/beech-api - issues
- E-mail: [email protected]
- Facebook: https://www.facebook.com/bombkiml
The Beech API framework is open-sourced software licensed under the MIT license.