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 🙏

© 2025 – Pkg Stats / Ryan Hefner

joixsql

v1.1.6

Published

*Well, now you can.*

Readme

What if you could automatize your MySQL/MariaDB table creation and migration based on your Joi schemas ?

Well, now you can.

Get Started:

import { Joi, TableEngine, config, Ecosystem, MigrationManager } from 'joixsql'

/* Create a todo schema */
const Todo = Joi.object({
    id: Joi.number().autoIncrement().primaryKey(),
    content: Joi.string().min(1).max(400).default(''),
    created_at: Joi.date().default(() => new Date()),
})

/* Connect the schema with a table name */
const todoTable = {schema: Todo, tableName: 'todos'}

/* Instance a new ecosystem of Tables */
const ecosystem = new Ecosystem()
ecosystem.add(todoTable)

/* Do every available tests to check the model is receivable by MySQL/MariaDB */
ecosystem.verify(todoTable).all()

//We set the package configuration before running the table builder and the migration detector.
config.set({
    historyDir: './history',
    mysqlConfig: {
        host: 'localhost',
        user: 'user',
        password: 'password',
        database: 'database'
    },
    ecosystem: ecosystem 
})

const main = async () => {

    /* Will build all the tables present in the ecosystem that have not been created yet. */
    await TableEngine.buildAllFromEcosystem()

    /*
    Will migrate all the tables present in the ecosystem for the already existing tables
    that differ from their previous state recorded in the history
    */
    await MigrationManager.smartMigration()
}

main()

Extensions :

General:

general: unique

unique() set a SQL Unique constraint

Joi.object({
    email: Joi.string().email().unique()
})

general: group

group() has NO effect on MySQL/MariaDB. Feature enabled to allow feature developement on top of JOIxSQL, for classifying columns data, to render them only when they are included in a group, to avoid rendering the whole object when no need.

Joi.object({
    email: Joi.string().email().group(['full', 'preview'])
})

general: Default

default() will do a DEFAULT constraint on MySQL/Maria

Joi.object({
    count: Joi.number().max(150).min(0).default(0)
})

general: Foreign Key

foreignKey() indicates that 'title' is the FOREIGN KEY of the column 'id' in the table 'categories'

Joi.object({
    title: Joi.string().foreignKey('categories', 'id')
})

general: Cascades (only with foreign key)

Joi.object({
    title: Joi.string().foreignKey('categories', 'id').deleteCascade().updateCascade()
})

general: Populate

populate() indicates the link between two columns from different tables without sql consequences. This extension has been added to enable feature developement on top of JOIxSQL for formating rendered data for example.

Joi.object({
    title: Joi.string().populate('categories', 'id')
})

general: Required

required() set the column as NOT NULL SQL constraint

Joi.object({
    title: Joi.string().allow("Lord", "King", "Prince").required()
})

Strings

strings: email and other types

String types like email() automatically set the column's right data type:

  • email, domain, hostname, ipVersion: 255 chars max.
  • dataUri, uri, uriCustomScheme, uriRelativeOnly: 90,000 chars max.
  • guid: 70 chars max.
  • creditCard, ip, isoDate, isoDuration: 32 chars max.
Joi.object({
    email: Joi.string().email(),
    credit_card: Joi.string().creditCard()
    ...
})

strings: min() / max()

min(), and max() will determine the sql data type. https://www.mysqltutorial.org/mysql-text/

Joi.object({
    username: Joi.string().min(3).max(20)
})

strings: Nothing

If no max() nor string type is set, the SQL type will be by default TEXT (max 65,535 chars)

Joi.object({
    username: Joi.string()
})

strings: Allow (Enum)

allow() set the column as a MySQL/Maria ENUM

Joi.object({
    title: Joi.string().allow("Lord", "King", "Prince")
})

Numbers

numbers: Primary key

Joi.object({
    id: Joi.number().primaryKey()
})

numbers: Auto increment

Increment each new row on MYSQL / MariaDB

Joi.object({
    id: Joi.number().primaryKey().autoIncrement()
})

numbers: Float

Float number type: https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html

Joi.object({
    //max 999,999,999.99; min -999,999,999.99
    amount: Joi.number().float(11, 2)
    //max 99.999; min -99.999
    amount_2: Joi.number().float(5, 3)
})

numbers: Double

Double number type: min -1.7976931348623157E+308, max 1.7976931348623157E+308

Joi.object({
    stars_count: Joi.number().double()
})

numbers: Allow (Enum)

allow() set the column as a MySQL/Maria ENUM

Joi.object({
    class: Joi.number().allow(1, 2, 3)
})

numbers: port

Numbers types like portSet() automatically set the column's right data type:

  • portSet: int unsigned | min: 0, max: 4,294,967,295.
Joi.object({
    port: Joi.number().port(),
})

numbers: min() / max()

min(), and max() will determine the sql data type (https://github.com/elzeardjs/joixsql/blob/master/src/table-engine/mysql/types.ts)

Joi.object({
    //Here: Unsigned int
    player_id: Joi.number().min(0).max(2_000_000_000)
})

numbers: positive

positive() is equivalent to min(>=0). It will set the number as unsigned (if integers)

Joi.object({
    //Here: Unsigned int
    player_id: Joi.number().positive().max(2_000_000_000)
})