Introduction

This is a collection of Banyumuli modules that can be used to build a basic RESTful API. The code includes modules for creating models, controllers, and validation rules. These modules can be used as building blocks for your application.

Requirements

To use the BanyuMili framework effectively, please ensure that your development environment meets the following requirements:

  • Node.js version 16 or higher:
    BanyuMili framework requires Node.js version 16 or higher to function properly. Ensure that you have Node.js installed on your system and that it meets the minimum required version.
  • Package Manager:
    BanyuMili uses npm (Node Package Manager) or Yarn as its package manager. Make sure you have either npm or Yarn installed on your system to manage the framework's dependencies.
  • Operating System:
    BanyuMili is compatible with major operating systems such as Windows, macOS, and Linux. Ensure that your operating system is supported and meets the minimum requirements for Node.js and the package manager you choose.

Installation

To install the BanyuMili framework, follow these steps:

  1. Ensure that you have Node.js version 16 or higher installed on your system.
  2. Open your terminal or command prompt.
  3. Navigate to your project directory.
  4. Run the command npm install -g create-banyumili or npm link create-banyumili to install the framework and its dependencies.
  5. Once the installation is complete, you can create Banyumili with run the command create-banyumili specificFolder

Usage

Here's an example of how you can use the modules provided in this codebase to build a basic RESTful API:

Models

To create a model, extend the Model class and configure it using the following methods:

  • setTable(table_name): Set the name of the database table associated with the model.
  • setPrimaryKey(primary_key): Set the primary key field for the table.
  • setAllowedFields(fields): Set an array of allowed fields for the table.
  • setTimestamps(bool): Enable/disable automatic timestamp fields ('created_at' and 'updated_at').
  • setSoftDelete(bool): Enable/disable automatic soft delete.

const Model = require("./Model.js");
class UsersModel extends Model {
	constructor() {
		super();
		this.setTable("users");
		this.setPrimaryKey("id");
		this.setAllowedFields([
			'column1',
			'column2',
			'column3'
				]);
		this.setTimestamps(true);
		this.setSoftDelete(false);
	}
}
							

Controllers

To create a controller, extend the BaseController class and define the methods that will handle HTTP requests. You can also use the valid method to define validation rules for each request.

The BaseController class provides a way to create a controller in Node.js that handles incoming requests and returns responses. It includes methods for validating input data, accessing a model class to retrieve data from a database, and more.

								
class UserController extends BaseController{

	testUser = async (req, res) => {
		const users = await this.users.getResult();
		res.send(users);
	}
}
								

Routes

express.Router() method is used to create an instance of a router object that is assigned to routes variable. The Router() method is a middleware function provided by the Express.js framework that allows you to define routes for HTTP methods like GET, POST, PUT, DELETE, etc.

On Routes you just define the routes in this block like code below

								
defineRoutes() {
	const routes = express.Router();

	routes.get("/test", this.user.testUser.bind(this.user));
	routes.post("/testPost", this.user.createUser.bind(this.user));

	return routes;
}
								

After defining the routes, the routes object is returned from the defineRoutes() method. The returned object can be used to mount these routes to the server using app.use() method in the main application file.

Overall, this code block provides a way to define routes for a specific part of your application and export them for use in other parts of your application. This promotes modularity and separation of concerns in your application.

Valiidation

The Validation class can be used in a controller to validate incoming request data. Untuk membuatnya cukup buat rules seperti dibawah ini. To make it enough to create rules like below

								
const isValid = {
	email: {
		required: true,
		is_email: true
	},
	password: {
		required: true,
		minLength: 8
	}
};
								

In the example above, the variable isValid instantiated with an object that contains two properties, email and password. Each property represents a key in the incoming request data that needs to be validated. The validation rules are specified as key-value pairs in the object.

In this case, the email property is set to require a value (required: true) and to be a valid email address (is_email: true). The password property is set to require a value (required: true) and to have a minimum length of 8 characters (minLength: 8).

Validation Rules

Rule Description Example
required Value must be present and not empty. { username: { required: true } }
minLength Value must be at least the specified length. { password: { minLength: 8 } }
is_email Value must be a valid email address. { email: { is_email: true } }
alpha_numeric Value must contain only letters and numbers. { username: { alpha_numeric: true } }
alpha_numeric_space Value must contain only letters, numbers, and spaces. { full_name: { alpha_numeric_space: true } }
valid_json Value must be a valid JSON string. { data: { valid_json: true } }
valid_url Value must be a valid URL. { website: { valid_url: true } }
valid_ip Value must be a valid IP address. { ip_address: { valid_ip: true } }
alpha_dash Value must contain only letters, numbers, and dashes. { slug: { alpha_dash: true } }
alpha_space Value must contain only letters and spaces. { first_name: { alpha_space: true } }
alpha_numeric_punct Value must contain only letters, numbers, and punctuation marks. { message: { alpha_numeric_punct: true } }
regex_match Value must match the specified regular expression. { code: { regex_match: "/^[A-Z]{3}-[0-9]{3}$/" } }
valid_date Value must be a valid date. { dob: { valid_date: true } }
valid_cc_number Value must be a valid credit card number. { cc_number: { valid_cc_number: true } }
is_unique Value must be unique in the specified table and column. { email: { is_unique: "users.email" } }

Example Using Validation on Controllers

								
createUser = async (req, res) => {
	const {
		username,
		fullname,
		email,
		password
	} = req.body;
	const isValid = {
		username: {
			required: true,
			minLength: 6,
			alpha_numeric: true,
		},
		fullname: {
			required: true,
			minLength: 6,
			alpha_numeric_space: true,
		},
		email: {
			required: true,
			is_email: true,
			is_unique: 'users.email',
		},
		password: {
			required: true,
			minLength: 8,
		},
	}
	const errors = await this.valid(isValid).check()(req, res);
	if (errors && errors.length > 0) {
		res.status(400).json({
			error: errors
		});
	} else {
		res.status(201).json({
			message: "User created successfully"
		});
	}
}						
									

Query Builder

The Service class is a helper class for executing queries on a MySQL database. It provides methods for constructing SELECT, INSERT, UPDATE, and DELETE queries, as well as setting various query options.

Build your query by chaining methods such as select, where, whereRaw, whereLike, whereBetween, whereIn, join, leftJoin, limit, orderBy, groupBy selectMax, query, first, getResult, save, update, delete. For example:

select(...columns)

							
const result = await this.select('column1', 'column2').getResult();
							
						  

where(column, value)

							
const result = await this.where('column', 'value').getResult();
							
						  

whereRaw(condition)

							
const result = await this.whereRaw('column > 10').getResult();
							
						  

whereLike(condition)

							
const result = await this.whereLike('column', 'value').getResult();
							
						  

whereBetween(column, start, end)

							
const result = await this.whereBetween('column', 1, 10).getResult();
							
						  

whereIn(column, values)

							
const result = await this.whereIn('column', [1, 2, 3]).getResult();
							
						  

join(table, condition)

							
const result = await this.join('table2', 'table1.id = table2.table1_id').getResult();
							
						  

leftJoin(table, condition)

							
const result = await this.leftJoin('table2', 'table1.id = table2.table1_id').getResult();
							
						  

limit(limit)

							
const result = await this.limit(10).getResult();
							
						  

orderBy(order)

							
const result = await this.orderBy('column ASC').getResult();
							
						  

groupBy(group)

							
const result = await this.groupBy('column').getResult();
							
						  

selectMax(column, alias)

							
const result = await this.selectMax('column', 'maxValue').getResult();
							
						  

first()

							
const record = await this.first();
							
						  

query(sql, replacements)

							
const records = await this.query('SELECT * FROM table');
							
						  

getResult()

							
const result = await this.getResult();
							
						  

save(data)

							
const record = await this.save(data);
							
						  

update(id, data)

							
const record = await this.update(id, data);
							
						  

delete(id)

							
const record = await this.delete(id);
							
						  

Code Example

							
const result = await this
	.select('column1', 'column2')
	.where('column', 'value')
	.orderBy('column ASC')
	.limit(10)
	.getResult();