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

node-mysql-query-utils

v1.0.4

Published

A simple MySQL query utils for Node.js

Downloads

26

Readme

node-mysql-query-utils

A MySQL helper to provide ways to connect to the database, build SQL queries, and perform common database operations for Node.js.

npm version

Table of contents

Introduction

node-mysql-query-utils is a MySQL query builder and helper for Node.js. It provides a simple and easy way to build and execute MySQL queries.

Installation

npm install node-mysql-query-utils

or

yarn add node-mysql-query-utils

Overview

This package provides three classes to help you manage and interact with your MySQL database:

  1. DatabaseManagement
  2. SQLBuilder
  3. TableModel

Quick Start

Here’s a quick overview of how to make use of this library:

import {
  DatabaseManagement,
  TableModel,
  SQLBuilder,
  sqlHelper,
} from "node-mysql-query-utils";

// entry point of the application e.g. start server
// index.ts
DatabaseManagement.connectMultipleDatabases([
  {
    identifierName: "mainDB",
    config: {
      host: "localhost",
      user: "root",
      password: "password",
      database: "test_db",
    },
    options: {
      verbose: true, // optional, default is true. If true, will log all queries to console
    },
  },
]);

//or

DatabaseManagement.connectSingleDatabase(
  "mainDB",
  {
    host: "localhost",
    user: "root",
    password: "password",
    database: "test_db",
  },
  {
    verbose: true, // optional, default is true. If true, will log all queries to console
  }
);

// model folder
// user.ts
const mainDB = DatabaseManagement.getInstance("mainDB"); // get instance of mainDB
const columns = sqlHelper.createColumns([
  "user_id",
  "ctime",
  "utime",
  "email",
  "mobile",
  "password",
  "is_active",
  "is_deleted",
]);
export const userAccountModel = mainDB.createTableModel({
  tableName: "user_account",
  primaryKey: "user_id",
  columns,
  centralFields: {
    ctimeField: "ctime", // created_at column name in db
    utimeField: "utime", // updated_at column name in db
    isActiveField: "is_active", // is_active column name in db
    isDeletedField: "is_deleted", // is_deleted column name in db
    statusField: "status", // status column name in db
  },
});

// usage of userAccountModel in other files e.g. api-related files
// get user by id

DatabaseManagement

The DatabaseManagement class is a singleton class that helps manage database connections. It supports connecting to single or multiple databases and provides a way to retrieve instances of the connections.

Single database connection

import { DatabaseManagement } from "node-mysql-query-utils";
import { ConnectionOptions } from "mysql2/promise";

// Define connection configurations
const config: ConnectionOptions = {
  host: "localhost",
  user: "root",
  password: "password",
  database: "test_db",
};

// Connect to a single database
DatabaseManagement.connectSingleDatabase("mainDB", config);

// Retrieve the instance and use it to perform database operations
const dbInstance = DatabaseManagement.getInstance("mainDB");

Multiple database connections

import { DatabaseManagement } from "node-mysql-query-utils";
import { type DatabaseConnectionConfig } from "node-mysql-query-utils/dist/dto/types";

// Define multiple connection configurations
const configs: DatabaseConnectionConfig[] = [
  {
    identifierName: "mainDB",
    config: {
      host: "localhost",
      user: "root",
      password: "password",
      database: "main_db",
    },
  },
  {
    identifierName: "analyticsDB",
    config: {
      host: "localhost",
      user: "root",
      password: "password",
      database: "analytics_db",
    },
  },
];

// Connect to multiple databases
DatabaseManagement.connectMultipleDatabases(configs);

// Retrieve instances and use them to perform database operations
const mainDBInstance = DatabaseManagement.getInstance("mainDB");
const analyticsDBInstance = DatabaseManagement.getInstance("analyticsDB");

SQLBuilder Class

The SQLBuilder class provides a way to build SQL queries for various operations such as SELECT, INSERT, UPDATE, DELETE, etc.

To generate the final SQL query and its parameters, you must call the .buildQuery() method at the end of your query-building process.

If the SQLBuilder constructor is provided with a queryFn, you can use the .executeQuery() method to execute the query directly.

Example

import { SQLBuilder, sqlHelper } from "node-mysql-query-utils";

// Define the table name
const tableName = "user_account";

const columns = sqlHelper.createColumns([
  "user_id",
  "ctime",
  "utime",
  "email",
  "mobile",
  "password",
  "is_active",
  "is_deleted",
]);

// typescript
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();

// Javascript - no type hinting, but still works. Suggest using TableModel class for better type hinting if using Javascript
const sqlBuilder = new SQLBuilder();

// Accept QueryFunction for SQLBuilder to enable query execution
const sqlBuilder = new SQLBuilder(db.query.bind(db)); // Optional: put your own query function here if you don't connect DB by DatabaseManagement class from this package

// Accept second generic type for query function
const sqlBuilder = new SQLBuilder<(typeof columns)[number], any>(
  db.query.bind(db)
); // Optional: put your own query function here if you don't connect DB by DatabaseManagement class from this package

// Call buildQuery to get the SQL query and parameters in the end
const { sql, params } = sqlBuilder.select().from(tableName).buildQuery();
// Can also use array destructuring
const [sql, params] = sqlBuilder.select().from(tableName).buildQuery();
// BuildQuery also accepts an options object. it will return complete query with format. params will be empty array if format is true
const [sql, params] = sqlBuilder
  .select()
  .from(tableName)
  .buildQuery({ format: true });

// run your own query function if you don't connect DB by DatabaseManagement class from this package
const result = await db.query(sql, params);

// if query function is provided in SQLBuilder, you can execute the query directly
const result = await sqlBuilder.select().from(tableName).executeQuery();

.select() Method

// Select all columns, default is '*'
const [sql, params] = sqlBuilder.select().from(tableName).buildQuery();
const [sql, params] = sqlBuilder.select("*").from(tableName).buildQuery();

// Select specific columns
const [sql, params] = sqlBuilder
  .select(["user_id", "email"])
  .from(tableName)
  .buildQuery();

// Select columns with aliases
const [sql, params] = sqlBuilder
  .select([{ user_id: "id", mobile: "user_mobile" }, { email: "user_email" }])
  .from(tableName)
  .buildQuery();

// Select a single column
const [sql, params] = sqlBuilder.select("user_id").from(tableName).buildQuery();

.from() Method

// No alias
const [sql, params] = sqlBuilder.select().from("user_account").buildQuery();

// alias example
const [sql, params] = sqlBuilder
  .select()
  .from("user_account", "u")
  .buildQuery();
const [sql, params] = sqlBuilder.select().from("user_account u").buildQuery();

.join() Method

// Inner join
const [sql, params] = sqlBuilder
  .select()
  .from("user_account", "u")
  .join(
    "INNER",
    "user_profile_pic",
    "up",
    "u.user_profile_pic_id = up.user_profile_pic_id"
  )
  .buildQuery();

// Left join
const [sql, params] = sqlBuilder
  .select()
  .from("user_account", "u")
  .join(
    "LEFT",
    "user_profile_pic",
    "up",
    "u.user_profile_pic_id = up.user_profile_pic_id"
  )
  .buildQuery();

// Right join
const [sql, params] = sqlBuilder
  .select()
  .from("user_account", "u")
  .join(
    "RIGHT",
    "user_profile_pic",
    "up",
    "u.user_profile_pic_id = up.user_profile_pic_id"
  )
  .buildQuery();

Only provide third argument if no alias is needed

// Inner join
const [sql, params] = sqlBuilder
  .select()
  .from("user_account", "u")
  .join(
    "INNER",
    "user_profile_pic",
    "u.user_profile_pic_id = user_profile_pic.user_profile_pic_id"
  )
  .buildQuery();

.where() Method

// All condition examples
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .where({
    email: "[email protected]", // equal to '
    email: { "=": "[email protected]" }, // equal to '
    email: { "!=": "[email protected]" }, // not equal to
    user_id: { ">": 123 },
    user_id: { "<": 123 },
    user_id: { ">=": 123 },
    user_id: { "<=": 123 },
    is_active: { BETWEEN: [0, 1] },
    is_active: { NOT_BETWEEN: [0, 1] },
    status: { IN: [1, 2, 3, 4] },
    status: { NOT_IN: [1, 2, 3, 4] },
    nickname: { IS_NOT_NULL: true }, // must be true, false will throw error
    nickname: { IS_NULL: true }, // must be true, false will throw error
    nickname: { LIKE: { contains: 'name' } }, // contains 'name'
    nickname: { NOT_LIKE: { startsWith: 'name' } }, // not starts with 'name'
    nickname: { LIKE: { endsWith: 'name' } }, // ends with 'name'
    nickname: { LIKE: '%_123' } // custom pattern
    nickname: { REGEXP: '^[a-zA-Z0-9]*$' } // custom pattern
    "u.user_id": { "!=": 1 }, // assume alias is set in From's second parameters (e.g. .from("user_account", "u"))
  })
  .buildQuery();
// AND example
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .where({
    email: "[email protected]",
    is_active: 1,
  })
  .buildQuery();

// alternative AND example
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .where({
    AND: [{ email: { LIKE: "%@gmail.com" } }, { username: "jane" }],
  });
// OR example
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .where({
    OR: [{ email: { LIKE: "%@gmail.com" } }, { username: "jane" }],
  });

Supported Operators:

  • =
  • !=
  • >
  • <
  • >=
  • <=
  • LIKE,
  • NOT_LIKE
  • REGEXP,
  • IN,
  • NOT_IN
  • BETWEEN
  • NOT_BETWEEN
  • IS_NULL
  • IS_NOT_NULL

.orderBy() Method

// Single order by
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .orderBy([{ field: "email", direction: "ASC" }])
  .buildQuery();

// Multiple order by
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .orderBy([
    { field: "email", direction: "ASC" },
    { field: "user_id", direction: "DESC" },
  ])
  .buildQuery();

.limit() and .offset() Methods

// Limit
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .limit(10)
  .buildQuery();

// Limit and offset
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .limit(10)
  .offset(5)
  .buildQuery();

.insert() Method

// Insert single row
const [sql, params] = sqlBuilder
  .insert(
    "user_account",
    { email: "[email protected]" },
    {
      enableTimestamps = false, // if true, will add ctime and utime to insert object
      ctimeField = "ctime",
      utimeField = "utime",
      ctimeValue = Math.floor(Date.now() / 1000), // default is current unix timestamp
      utimeValue = Math.floor(Date.now() / 1000), // default is current unix timestamp
      insertIgnore = false, // if true, will add IGNORE to the insert query
    }
  )
  .buildQuery();

Insert Options

The insert method accepts options parameter with the following properties:

| Property | Type | Description | | ------------------ | ------- | ------------------------------------------------------------------------------------- | | enableTimestamps | boolean | (Optional) If true, will add ctime and utime to the insert object. Default is false. | | ctimeField | string | (Optional) The field name for the create timestamp. Default is ctime. | | utimeField | string | (Optional) The field name for the update timestamp. Default is utime. | | ctimeValue | any | (Optional) The value for the create timestamp. Default is the current Unix timestamp. | | utimeValue | any | (Optional) The value for the update timestamp. Default is the current Unix timestamp. | | insertIgnore | boolean | (Optional) If true, will add IGNORE to the insert query. Default is false. |

.update() Method

// Update Method 1
const [sql, params] = sqlBuilder
  .update(
    "user_account",
    { email: "[email protected]" },
    // Options
    {
      enableTimestamps = false, // if true, will add utime to update object
      utimeField = "utime",
      utimeValue = Math.floor(Date.now() / 1000), // default is current unix timestamp
    }
  )
  .where({ user_id: 1 })
  .buildQuery();

// Update Method 2 (Options not supported yet)
const [sql, params] = sqlBuilder
  .update("user_account")
  .set({ email: "[email protected]" })
  .where({ user_id: 1 })
  .buildQuery();

// Increment and Decrement (Added in version v1.0.4)
const [sql, params] = sqlBuilder
  .update("user_account")
  .set({ balance: { increment: 100 } })
  .where({ user_id: 1 })
  .buildQuery();

Update Options

The update method accepts options parameter with the following properties:

| Property | Type | Description | | ------------------ | ------- | ------------------------------------------------------------------------------------- | | enableTimestamps | boolean | (Optional) If true, will add utime to the update object. Default is false. | | primaryKey | string | (Optional) The primary key field name. For removing primaryKey in update object | | utimeField | string | (Optional) The field name for the update timestamp. Default is utime. | | utimeValue | any | (Optional) The value for the update timestamp. Default is the current Unix timestamp. |

.delete() Method

// Delete Whole Table
const [sql, params] = sqlBuilder.deleteFrom("user_account").buildQuery();

// Delete with where
const [sql, params] = sqlBuilder
  .deleteFrom("user_account")
  .where({ user_id: 1 })
  .buildQuery();

// Delete with limit
const [sql, params] = sqlBuilder
  .deleteFrom("user_account")
  .where({ user_id: { ">": 1 } })
  .limit(1)
  .buildQuery();

.buildQuery() Method

// Build query with format
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const [sql, params] = sqlBuilder
  .select()
  .from("user_account")
  .buildQuery({ format: true });

.executeQuery() Method

// Execute query
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const result = await sqlBuilder.select().from("user_account").executeQuery();

Without calling .buildQuery() or .executeQuery()

// Without calling .buildQuery() or .executeQuery() as end of query building
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const result = sqlBuilder.select().from("user_account");

// result will be an instance of SQLBuilder
// SQLBuilder {
//   queryFn: [Function: bound executeQuery] AsyncFunction,
//   message: 'Call .buildQuery() or .executeQuery() to get the result'
// }

// To get the result, call .buildQuery() or .executeQuery()
const [sql, params] = result.buildQuery();
// or
const result = await result.executeQuery(); // if query function is provided in SQLBuilder

TableModel Class

The TableModel class is a wrapper around the SQLBuilder class that provides a way to build and execute common database operations like SELECT, INSERT, UPDATE, DELETE, etc.

To generate the final SQL query and its parameters, you must call the .buildQuery() method at the end of your query-building process. If you have provided a query function, you can use the .executeQuery() method to execute the query directly.

There are two ways to define and use the TableModel class:

1. Using DatabaseManagement to Connect to the Database

Connect database by DatabaseManagement class can refer to the Quick Start example. This method involves connecting to multiple databases using the DatabaseManagement class and then retrieving instances to create table models.

2. Using the TableModel Class Directly

Alternatively, you can define the table model by using the TableModel class directly. This method is useful if you prefer to use your own query function or if you don't connect to the database using the DatabaseManagement class from this package.

// Define the table model by using the TableModel class directly
const userModel = new TableModel({
  tableName: "users",
  primaryKey: "user_id",
  columns: sqlHelper.createColumns(["user_id", "name", "email", "phone"]),
  queryFn: db.query.bind(db), // Optional: put your own query function here if you don't connect DB by DatabaseManagement class from this package
});

Methods

The TableModel class provides the following methods to perform database operations:

| Method | Description | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | | createSelect | Creates a SELECT query. Returns a function that returns an instance of the SQLBuilder class. You can chain the SQLBuilder methods to build your desired query. | | createInsert | Creates an INSERT query. Returns a function that returns an instance of the SQLBuilder class. You can chain the SQLBuilder methods to build your desired query. | | createUpdate | Creates an UPDATE query. Returns a function that returns an instance of the SQLBuilder class. You can chain the SQLBuilder methods to build your desired query. | | createDelete | Creates a DELETE query. Returns a function that returns an instance of the SQLBuilder class. You can chain the SQLBuilder methods to build your desired query. | | createCount | Creates a COUNT query. Returns a function that returns an instance of the SQLBuilder class. You can chain the SQLBuilder methods to build your desired query. | | findOne | Finds a single record. Returns an instance of the SQLBuilder class with the findOne method configured. | | findAll | Finds multiple records. Returns an instance of the SQLBuilder class with the findAll method configured. | | remove | Removes records based on conditions. Returns an instance of the SQLBuilder class with the remove method configured. | | removeOne | Removes a single record based on conditions. Returns an instance of the SQLBuilder class with the removeOne method configured. | | patchSingleField | Updates a single field in records based on conditions. Returns an instance of the SQLBuilder class with the patchSingleField method configured. | | softDeleteOne | Soft deletes a single record based on conditions. Returns an instance of the SQLBuilder class with the softDeleteOne method configured. | | softDelete | Soft deletes multiple records based on conditions. Returns an instance of the SQLBuilder class with the softDelete method configured. | |

The TableModel class provides the following methods to perform database operations.

Methods that start with create (e.g., createSelect, createInsert) return a function that returns an instance of the SQLBuilder class. You can chain the SQLBuilder methods to build your desired query.

Other methods, such as findOne, return an instance of the SQLBuilder class that is already configured with some chained methods. These methods act as wrapper functions for common CRUD operations and are not intended for further chaining.

createSelect

const selectUser = userModel.createSelect();
const result = await selectUser({
  fields: ["user_id", "email", "nickname"],
})
  .where({ user_id: 1 })
  .executeQuery();

createInsert

const insertUser = userModel.createInsert();
const result = await insertUser({
  data: { user_id: 1, email: "[email protected]", nickname: "John Doe" },
}).executeQuery();

createUpdate

const updateUser = userModel.createUpdate();
const result = await updateUser({
  data: { nickname: "John Doe 2" },
  where: { user_id: { "<=": 5 } },
})
  .limit(2)
  .executeQuery();

createDelete

const deleteUser = userModel.createDelete();
const result = await deleteUser({ where: { user_id: 1 } })
  .limit(1)
  .executeQuery();

createCount

const countResult = await countUser("user_id")
  .where({ user_id: { "<": 2 } })
  .executeQuery();

Common Parameters

The following table lists common parameters that many methods accept. Note that some parameters may be available for certain methods while others may not, as each method performs different operations. TypeScript will provide hints for the available parameters for each method.

| Parameter | Type | Description | | --------- | ------ | -------------------------------------------------------------------------------------------------------------- | | fields | Array | An array of strings specifying the columns to select. | | where | Object | An object specifying the conditions for the query. | | orderBy | Array | An array of objects specifying the columns to order by and the direction (ASC or DESC). | | limit | Number | A number specifying the maximum number of rows to return. | | offset | Number | A number specifying the offset of the first row to return. | | options | Object | An object specifying additional options for the query. Can be referenced in Update Options. |

findOne

const [user] = await userModel
  .findOne({ where: { user_id: 1 } })
  .executeQuery();

findAll

const users = await userModel
  .findAll({
    fields: ["user_id", "email"],
    where: { is_active: true },
    orderBy: [{ column: "user_id", direction: "ASC" }],
    limit: 10,
    offset: 0,
  })
  .executeQuery();

updateOne

const updatedOneUser = await userModel
  .updateOne({
    where: { user_id: 1 },
    data: { email: "[email protected]" },
  })
  .executeQuery();

updateAll

const updateAllUsers = await userModel
  .updateAll({
    data: { nickname: "John Doe" },
    where: { user_id: { "<=": 5 } },
    options: { enableTimestamps: true, utimeField: "utime" },
  })
  .executeQuery();

insertRecord

const insertedUser = await userModel
  .insertRecord({
    data: { user_id: 1, email: "[email protected]", nickname: "John Doe" },
    options: {
      enableTimestamps: true,
      ctimeField: "ctime",
      utimeField: "utime",
    },
  })
  .executeQuery();

removeOne

const deletedOneUser = await userModel
  .removeOne({
    where: { user_id: { ">": 1 } },
    orderBy: [{ field: "user_id", direction: "ASC" }],
  })
  .executeQuery();

remove

const deletedAllUsers = await userModel
  .remove({ where: { user_id: 1 } })
  .executeQuery();

patchSingleField

const patchedActiveField = await userModel
  .patchSingleField({
    patchField: "is_active",
    where: { user_id: 1 },
    value: 1,
    options: { enableTimestamps: true, utimeField: "utime" },
  })
  .executeQuery();

softDeleteOne

const softDeletedUser = await userModel
  .softDeleteOne({
    where: { user_id: 1 },
    value: 1,
    options: {
      enableTimestamps: true,
      deleteField: "is_deleted",
      utimeField: "utime",
    },
  })
  .executeQuery();

softDelete

const softDeletedUsers = await userModel
  .softDelete({
    where: { user_id: { ">": 1 } },
    value: 1,
    options: {
      enableTimestamps: true,
      deleteField: "is_deleted",
      utimeField: "utime",
    },
  })
  .executeQuery();

Changelog

Detailed changes for each version are documented in the CHANGELOG.md file.