npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

unsql

v1.6.16

Published

UnSQL can be defined as a light weight schemaless ORM. It provides clean and yet extensive interface to interact with MySQL Databases without getting into the complexities. It provides dynamic query generation through easy to understand Javascript based m

Downloads

26

Readme

UnSQL

UnSQL is a library, written in JavaScript. It provides for a modern way to interact with the MySQL databases. It provides simple yet very powerful interface that uses common JavaScript data forms like objects and arrays to define different query parameters and execute MySQL commands (with any level of complexity) without actually writing a single line of SQL. It automatically generates the structured query in the background and also takes care of the transactions, rollbacks and graceful termination. It also supports the option to enter structured SQL into the parameters for even more complex querying purposes.

Breaking Changes

Beyond this version (i.e. v1.6+) we are completely dropping the support for older callback based approach and also the dependency on mysql library in favor of newer promise based and mysql2 due to change in the MySQL password authentication since its version 8. You can easily swap in the new version by replacing the older mysql import with mysql2/promise and you would be good to go. Also, we will be dropping the support for functional based methods, retaining the class based approach only.

Features

  • Promise based
  • Light weight
  • No predefined schema required
  • Supports object oriented programing
  • Supports MySQL connection pool
  • Built-in dynamic Structured Query Generator
  • Supports structured sub-queries as value for several of its parameters
  • Built-in transactions for each query
  • Graceful handling of errors and exceptions
  • Query success or failure acknowledgement
  • Returns result as JSON object
  • Supports AES based Encryption and Decryption

Installation

Install UnSQL with npm


npm  install  unsql

OR


npm  i  unsql

Prerequisite

This package, although not directly dependent, but requires mysql2/promise package installed from npm install mysql2 and the MySQL connection pool to interact with the database.

Import

Import by using any one of the following methods:

CommonJS import

const  UnSQL = require('unsql')

OR

ES6 import

import  UnSQL  from  'unsql'

Usage

UnSQL provides three methods viz. find, save and del to perform the CRUD operations. These methods are designed to have a simple interface but are capable of generating any level of complex structured query.

Each of these three methods accept a plain JavaScript object (We call it the query object) with multiple parameters (optional) depending upon the function they are being passed in to. Some of the parameters also allow you to write multiple complete SQL as sub-query inside the value.

To access these three methods, you require a separate Model file corresponding to each of your database tables.

Model

Below are the examples of how to create a Model file for functional and object oriented programing:

Model Class:

Here Product is the demo Model class. By extending the Product with the UnSQL class, Product gains access to all the built-in functionalities and methods required to interact with the database.

Product.class.js

import  UnSQL  from  'unsql'

import  pool  from  'your-mysql-service'

class  Product  extends  UnSQL {

    // Database table to map this model class (Mandatory)
    static  TABLE_NAME = 'replace_with_db_table_name'

    // MySQL connection pool (Mandatory)
    static  POOL = pool

    // Declare database columns as class properties here (Optional)
    // Note: For "Auto Incrementing" column, use null or 0 as default value
    // firstColumnName // No default value provided
    // secondColumnName = 'Default Value'

    // Declare custom methods here (Optional)
    // Note: All methods must be declared as static
    // static test() {
        // // Code goes here
    // }

}

All of the aforementioned methods return the result as a promise, which then resolves (or rejects) into a JavaScript object, and every such result object has an acknowledgement status named success. It has a boolean value, which reflects the query being successful or failure.

Below is the example of the result object on failure:

resultObject = {
    success: false,
    error: { 'Actual error object containing code, message and stack' }
}

Below are the explanations to each of these functions and all the parameters of the query object associated with them.

find: Read / Retrieve

find method is used for the read / retrieve operations of the data from the database. It takes in multiple (optional) parameters, in a plain JavaScript object format, and generates a structured sql from these parameters. For the sake of explanation, we will call this object as findQuery. Below is an example of this findQuery object with all the parameters and their corresponding default values.

findQuery = {
    select: '*',
    alias: null,
    join: null,
    where: null,
    whereOr: null,
    junction: 'AND',
    groupBy: null,
    having: null,
    orderBy: null,
    orderDirection: 'DESC',
    rowCount: null,
    offset: null
}

Below is the example of the result resolved from the find method:

resultObject = {
    success: true,
    result: ['Array of results'] // Empty array [] if no results for matching conditions
}

findQuery

Below are the explanations for each of the parameters of the findQuery object:

select: It takes in a string value, containing various column names as a comma separated values. Default value is '*'. You may pass a full SQL as a sub-query inside this parameter to get value(s) from another table AS a field.

select = 'columnOne, columnTwo, (SELECT anotherColumn FROM anotherTable WHERE conditions...) AS columnThree'

alias: This parameter takes in a string value that you want to use as an alias name for the table associated with the Model. Default value is null. Passing this value enables you to use the same alias value as a prefix to all the associated columns, in all the other parameters. This parameter is extremely important and handy for writing join queries.

alias = 't1'

join: This parameter takes in an array of objects. Each object represents a unique join condition, and must have these exact three properties type, table and on. Default value is null.

  • type: It defines the type of join query, can have any one of the values of "LEFT", "RIGHT", "INNER", "OUTER", "CROSS" etc.
  • table: Table name (along with its alias) with which the Model's table has to be joined
  • on: Condition to map the join, as a string value
condition1 = { type: 'LEFT', table: 'firstTable a', on: 't1.commonColumn = a.commonColumn' }

condition2 = { type: 'LEFT', table: 'secondTable b', on: 't1.commonColumn = b.commonColumn' }

join = [ condition1, condition2 ]

where & whereOr: Both of these parameters accept a two dimensional array i.e. an array of array. Each child array represents a unique WHERE condition. The only difference between the two parameters is the joining clause used by them. where uses AND clause to join the conditions and whereOr uses OR as joining clause. Default value for both the parameters is null.

condition1 = [ 'columnOne', '=', value1 ]

condition2 = [`(columnTwo = '${value2}' OR columnThree > ${value3}) AND (anotherCondition) OR (anotherCondition)...`]

condition3 = ['columnFour','IN',`(SELECT anotherColumn FROM anotherTable WHERE conditions...)`]

where = whereOr = [condition1, condition2, condition3]

Here, condition1 represents typical condition array with three values:

  • columnName
  • Equalities, "IN", "NOT IN", "IS", "IS NOT" etc.
  • Value, "null", structured SQL

condition2 represents a more advanced level or pairing of multiple types of conditions inside a single array. This type of string can consist any number of conditions within, but with a limitation of being a single valued array. Notice we have not passed the second and third values here.

condition3 represents the example of using "IN" as a condition check and also shows passing a structured SQL as the value.

Please note: When working with alias and join same alias prefix have to be passed with the corresponding column names in these condition as well.

junction: This parameter accepts any one of the two string values AND, OR. Default value is AND. It acts as the joining clause to connect the where and whereOr parameters. It only comes into the picture if both where and whereOr are passed.

[where_conditions] (junction- 'AND' / 'OR') [whereOr_conditions]

groupBy: This parameter accepts a column name as a string value and groups the result rows based on this column. Default value is null. When using with alias and (or) join, corresponding prefix must be used.

groupBy = 'columnName'

having: This parameter accepts a string value, containing a condition with aggregate function. Default value is null. It is used in paired with the groupBy parameter. It is extremely useful because where and whereOr does not support the aggregate functions. When used with alias or join, corresponding prefix must be used.

having = 'COUNT(columnName) > someValue'

orderBy: This parameter accepts the column name as a string value. It is used to sort the result rows on the bases of this column. Default value is null. When used with alias or join, same prefix must be used.

orderBy = 'columnName'

orderDirection: This parameter is used in pair with the orderBy parameter and accepts any one of the two values ASC or DESC. It defines the order in which the sorting of the result rows must be done. Default value is DESC.

orderDirection = 'ASC'

rowCount: This parameter accepts an integer value and is used to set the maximum limit for the number of result rows that are required. Default value is null hence all the rows will be returned by default.

rowCount = 20

offset: This parameter accepts an integer value, it determines the start index for the result rows. All the entries that are before this index are skipped. Default value is null. This parameter paired with the rowCount parameter to to achieve server side pagination.

offset = 2

save: Insert / Update / Upsert

save method is used for insert / update / upsert operations of data into the database. It takes in a plain JavaScript object with multiple parameters, data being the only mandatory / required parameter among these.

For the sake of explanations, we will call this object as saveQuery.

Below is an example of this saveQuery object with all the parameters and their corresponding default values:

saveQuery = {
    alias: null,
    data,
    updateObj: null,
    where: null,
    whereOr: null,
    junction: 'AND'
}

Depending upon the combinations of parameters passed, save method will automatically perform different type of operations.

Different combinations of parameters to achieve different operations are explained below:

Insert: When only data parameter is passed inside the saveQuery, the save method will generate insert sql.

saveQuery = { data: dataToBeInserted }

Update: When where and (or) whereOr parameters are passed along with the data parameter inside the saveQuery, the save method will generate update sql and perform an update operation with corresponding conditions passed inside the where and (or) whereOr parameters.

Sample 1


saveQuery = {
    data: dataToBeUpdated,
    where: [conditions]
}

Sample 2


saveQuery = {
    data: dataToBeUpdated,
    whereOr: [conditions]
}

Sample 3


saveQuery = {
    data: dataToBeUpdated,
    where: [conditions1],
    whereOr: [conditions2],
    junction: 'OR'
}

Upsert: When updateObj parameter is passed along with the data parameter inside the saveQuery, the save method will generate upsert sql and perform an upsert operation by updating the corresponding columns with their values passed inside the updateObj parameter.


saveQuery = {
    data: dataToBeInserted,
    updateObj: dataToBeUpdated
}

saveQuery

Below are the explainations for data and updateObj parameters of the saveQuery object. Remaining parameters are exactly the same as explained above for the findQuery object.

data: This parameter accepts data in two forms:

  • Javascript object for insert / update of single row
  • Array or javascript objects for inserting multiple rows at once.

updateObj: This parameter is optional and is only used for upsert operations. This accepts data as javascript object, however, requires only that part of data that needs to be updated in case of "Duplicate Primary Key" is found in the data parameter.

Below is the example of the result resolved from an save method after insert operation:


resultObject = {
    success: true,
    insertID: 'ID_of_newly_added_row'
}

For update and upsert operations this "insertID" field will return "0" as value.

del: Delete / Remove

del method is used to perform delete operation of data from the database. It accepts a plain javascript object with multiple parameters, for the sake of explanation, we will call this object as delQuery. It removes one or multiple rows at once depending upon the conditions passed inside the where and (or) whereOr parameters.

Below is the example for this saveQuery object with all the parameters and their corresponding default values:


delQuery = {
    where: null,
    whereOr: null,
    junction: 'AND'
}

All the parameters passed here are already explained above, inside the findQuery object. Please read the above explanations for these parameters.

Examples

For all the below examples we assume these samples are existing inside express app, Product is the Model Class imported into the same routes file, and all the above setup is complete. "ID" here is the demo field that may represent your primary key or any identifier. Depending upon if result is resolved or rejected, Products variable will get the result object as mentioned above.

Example 1: Read data from the database

router.get('/products',async (req,res)=>{

    const  select = 'ID, title, description'

    const  Products = await  Product.find({ select }).catch(err  =>  err)

})

Example 2: Read data from the database with where clause

router.get('/products/:id',async (req,res) => {

	const { id } = req.params
	const  select = 'ID, title, description'
	const  where = [['ID','=', id]]

	const  Products = await  Product.find({ select, where }).catch(err  =>  err)

})

Example 3: Insert data in the database

router.post('/products',async (req,res)=>{

	const  data = req.body
	const  Products = await  Product.save({ data }).catch(err  =>  err)

})

Example 4: Update data in the database

router.put('/products/:id',async (req,res) => {

	const { id } = req.params
	const  data = req.body
	const  where = [['ID','=', id]]

	const  Products = await  Product.save({ data, where }).catch(err  =>  err)

})

Example 5: Upsert data in the database

router.post('/products',async (req,res)=>{

	const  data = req.body
	const { ID, ...updateObj } = data

	const  Products = await  Product.save({ data, updateObj }).catch(err  =>  err)

})

Example 6: Delete data in the database

router.delete('/products/:id',async (req,res)=>{

	const { id } = req.params
	const  where = [['ID','=', id]]

	const  Products = await  Product.del({ where }).catch(err  =>  err)

}) 

Author