# Getting Started

<figure><img src="https://2684121194-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCE40T5ADNteu7XvszmlE%2Fuploads%2FLk1czD3d4h4Ay4a3FLyt%2FPicsart_25-02-07_02-39-46-166.png?alt=media&#x26;token=8a10d808-bb1a-481f-ae13-b0fa65785f22" alt=""><figcaption></figcaption></figure>

***NexORM*** is a powerful ORM designed to simplify database management while delivering high performance and flexibility. Inspired by [**MongoDB**](https://www.mongodb.com/docs/), [**Prisma**](https://www.prisma.io/docs), and [**TypeORM**](https://typeorm.io/), it combines the best features of these tools, offering advanced operators (like $set and $inc with more), a built-in caching system, and a <mark style="color:purple;">**decorator-based**</mark> schema definition for clean and intuitive modeling.

With full <mark style="color:blue;">**TypeScript**</mark> support, ***Nexorm*** ensures  <mark style="background-color:yellow;">**type-safe**</mark> , modern development using ~~<mark style="color:yellow;">**JavaScript (ES2021)**</mark>~~. It supports **MySQL**, **PostgreSQL**, **SQLite**, **MariaDB**, and **MSSQL**, making it suitable for projects of any scale, from small apps to complex enterprise systems.

Start building with ***NexORM*** to enjoy effortless, scalable, and maintainable database interactions.

## Features

* **Full Type Support:** *Seamless TypeScript integration for type-safe development.*
* **Decorator-Based Schema Definition:** *Clean and intuitive schema modeling using decorators.*
* **Multi-Database Support:** *Compatible with MySQL, PostgreSQL, SQLite, MariaDB, and MSSQL.*
* **Full JSON Support:** *Easily handle arrays and objects in JSON format.*
* **Hooks Support:** *Lifecycle hooks for enhanced control over database events.*
* **Encryption, Decryption, and Hashing:** *Built-in utilities for secure data management.*
* **Validation Support:** *Ensure data integrity with powerful validation tools.*
* **Multi-Connection Support:** *Manage multiple database connections effortlessly.*
* **CLI Support:** *Command-line tools for streamlined database operations.*
* **Cache Support:** *Built-in caching for faster queries and improved performance.*
* **Index Support:** *Optimize queries with advanced indexing capabilities.*
* **Advanced Operator Support:** *Extendable operators for flexible database operations.*
* **Debug and Logging Support:** *Track and troubleshoot with detailed logs and debug tools.*

And more...

***With NexORM your schemas & models look like this:***

```typescript
/* ./schemas/user.ts */
import Model from 'nexorm/model';
import { 
  Schema, Timestamps, 
  Column, Default, Required 
} from 'nexorm/decorators';

@Schema
@Timestamps /* UpdatedAt And CreatedAt Sections */
class UserSchema {

@Column
@Required
static personName = String; /* Required String Column */

@Column
@Required
static personSurname = String; /* Required String Column */

@Column
@Default(16)
static personAge = Number; /* Number Column If Value Is Not Available */
                            /* Value Is Set To '16' */

@Column
@Default(['Personal'])
static tags = Array(String); /* String[] Column If Value Is Not Available */
                                 /* Value Is Set To '["Personal"]' */

@Column
static audit = Object; /* Object Column */

};

/* Integrating The Schema Into The Model And Exporting */
export default new Model(UserSchema);

```

***And your domain logic will look this way:***

```typescript
import User from './schemas/user';

const allUsers = await User.$everything();
const firstUser = await User.$searchFirst();

const filteredUsers = await User.$search({
   $where: {
         personName: 'John',
         personAge: {
             $gte: 18
         }
   }
});

const findUser = await User.$searchOne({
    $where: {
        tags: {
            $in: [['Personal']]
        }
    },
    $options: {
        $sort: {
            personAge: -1
        }
    }
});

```

## Installation <a href="#installation" id="installation"></a>

1. **Install the npm package:**\ <mark style="color:blue;">**`npm install nexorm --save`**</mark> <br>
2. **You may need to install `reflect-metadata`:**\ <mark style="color:blue;">**`npm install reflect-metadata --save`**</mark> \
   **and import it somewhere in the global place of your app (for example in `src/index.ts`):**\ <mark style="color:blue;">**`import 'reflect-metadata';`**</mark><br>
3. **You may need to install node typings:**\ <mark style="color:blue;">**`npm install @types/node --save-dev`**</mark> <br>
4. **Install a database driver:**
   * for **MySQL**\ <mark style="color:green;">**`npm install mysql2 --save`**</mark>&#x20;
   * for **PostgreSQL**\ <mark style="color:green;">**`npm install pg --save`**</mark>&#x20;
   * for **SQLite**\ <mark style="color:green;">**`npm install sqlite3 --save`**</mark>&#x20;
   * for **Microsoft SQL Server**\ <mark style="color:green;">**`npm install tedious --save`**</mark>&#x20;
   * for **MariaDB**\ <mark style="color:green;">**`npm install mariadb --save`**</mark>&#x20;

### TypeScript Configuration

Also, make sure you are using TypeScript version **4.5** or higher, and you have enabled the following settings in **`tsconfig.json`**:

```json
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
```

You may also need to enable **`es6`** in the **`lib`** section of compiler options, or install **`es6-shim`** from **`@types`**.

## Quick Start

The quickest way to get started with NexORM is to use its CLI commands to generate a <mark style="color:blue;">**`nexorm.config.ts`**</mark> or ~~<mark style="color:yellow;">**`nexorm.config.js`**</mark>~~ file.

```typescript
nexorm init /* With Selection Prompts */
nexorm init -y /* Skip All Prompts */
nexorm init --database sqlite --language ts --babel false /* For Manuel */
```

After edit the <mark style="color:blue;">**`nexorm.config.ts`**</mark> or ~~<mark style="color:yellow;">**`nexorm.config.js`**</mark>~~ file and put your own database connection configuration options in there:

```typescript
/* nexorm.config.ts */

/* eslint-disable @typescript-eslint/no-var-requires */
/** @type {import('nexorm').NexormConfig} */
import type { NexormConfig } from "nexorm";

export default [{
    $provider: "nexorm",
    $database: "sqlite",
    $databaseEngine: "InnoDB",
    $filePath: "./nexorm.sqlite",
    $autoConnect: true,
    $onConnection: () => {
        console.log("[Nexorm] Database ready!");
    },
    $onError: (error: Error) => {
        console.error("[Nexorm] Error connecting to database:", error);
    },
}] satisfies NexormConfig;
```

### Configuration File Options

You can adjust the configuration file according to your needs using the table below.

<table><thead><tr><th width="205" align="center" valign="top">Value</th><th width="375" align="center">Type</th><th>Default</th></tr></thead><tbody><tr><td align="center" valign="top"><strong><code>$provider</code></strong><mark style="color:red;"><strong><code>*</code></strong></mark></td><td align="center"><mark style="color:blue;"><strong>'nexorm'</strong></mark><strong> </strong><mark style="color:green;"><strong>|</strong></mark> <mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:yellow;"><strong><code>nexorm</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$database</code></strong><mark style="color:red;"><strong><code>*</code></strong></mark></td><td align="center"><mark style="color:blue;"><strong>'mysql'</strong></mark><strong> </strong><mark style="color:green;"><strong>|</strong></mark><strong> </strong><mark style="color:blue;"><strong>'postgres'</strong></mark><strong> </strong><mark style="color:green;"><strong>|</strong></mark><strong> </strong><mark style="color:blue;"><strong>'sqlite'</strong></mark><strong> </strong><mark style="color:green;"><strong>|</strong></mark><strong> </strong><mark style="color:blue;"><strong>'mariadb'</strong></mark><strong> </strong><mark style="color:green;"><strong>|</strong></mark><strong> </strong><mark style="color:blue;"><strong>'mssql'</strong></mark> </td><td><mark style="color:yellow;"><strong><code>sqlite</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$dialectModule</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:yellow;"><strong>any</strong></mark></td><td><strong><code>(Empty)</code></strong></td></tr><tr><td align="center" valign="top"><strong><code>$autoConnect</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:green;"><strong>Boolean</strong></mark></td><td><mark style="color:yellow;"><strong><code>true</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$filePath</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:yellow;"><strong><code>./nexorm.sqlite</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$databaseEngine</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:yellow;"><strong><code>B-tree</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$ssl</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:green;"><strong>Boolean</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$pool</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:purple;"><strong>Object</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$pool.</code></strong><mark style="color:yellow;"><strong><code>$acquire</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:red;"><strong>Number</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$pool.</code></strong><mark style="color:yellow;"><strong><code>$idle</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:red;"><strong>Number</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$pool.</code></strong><mark style="color:yellow;"><strong><code>$max</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:red;"><strong>Number</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$pool.</code></strong><mark style="color:yellow;"><strong><code>$min</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:red;"><strong>Number</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$pool.</code></strong><mark style="color:yellow;"><strong><code>$evict</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:red;"><strong>Number</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><mark style="color:purple;"><strong><code>$onConnection</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="background-color:purple;"><strong>Function</strong></mark></td><td><mark style="color:purple;"><strong><code>(() ⇒ {..});</code></strong></mark></td></tr><tr><td align="center" valign="top"><mark style="color:purple;"><strong><code>$onDisconnect</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="background-color:purple;"><strong>Function</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><mark style="color:purple;"><strong><code>$onError</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="background-color:purple;"><strong>Function</strong></mark></td><td><mark style="color:purple;"><strong><code>(() ⇒ {..});</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$host</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$port</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$username</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$password</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$connectionURI</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:orange;"><strong>String</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$cache</code></strong><mark style="color:red;"><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:purple;"><strong>Object</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$cache.</code></strong><mark style="color:yellow;"><strong><code>$type</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:blue;"><strong>'memory'</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr><tr><td align="center" valign="top"><strong><code>$cache.</code></strong><mark style="color:yellow;"><strong><code>$duration</code></strong><strong><code>?</code></strong></mark></td><td align="center"><mark style="color:red;"><strong>Number</strong></mark></td><td><mark style="color:red;"><strong><code>(Empty)</code></strong></mark></td></tr></tbody></table>

## Create Model

Working with a database starts with creating tables. How do you tell **NexORM** to create a database table? The answer is - through the models. Your models in your app are your database tables.

For example, you have a **`Member`** model:

```typescript
@Schema
class Member {

@Column
@UUID()
static userId = String;

@Column
static username = String;

@Column
static displayName = String;

@Column
static age = Number;

@Column
static avatar = Buffer;

@Column
static banner = String;

@Column
static createdAt = Date;

@Column
static lastJoinedAt = Date;

@Column
@Hash('SHA256','hex')
static password = String;

@Column
@Default(false)
static isPremium = Boolean;

@Column
static badges = Array(String);

@Column
static logins = { timestamp: Number, ip: String };

};

export default new Model(Member);
```

And you want to store photos in your database. To store things in the database, first, you need a database table, and database tables are created from your models. Not all models, but only those you define as *entities*.

## Updating in the database <a href="#updating-in-the-database" id="updating-in-the-database"></a>

Now let's update a member from the database:

```typescript
import Member from './schemas/Member';
import * as fs from 'fs';



/* Update Or Create Row */
var upsertedMember = await Member.$upsert({
    $where: {
        isPremium: true
    },
    $update: {
        $toggle: {
            isPremium: true
        },
        $camelcase: {
            username: true
        }
    },
    $rules: {
        username: {
            $alphaNumeric: true
        }
    }
});


/* Update One Row */
await Member.$update({
    $where: {
        userId: '1234567890',
        username: 'fivesobes'
    },
    $update: {
        $set: {
            avatar: fs.readFileSync(path.join(__dirname, 'avatar.png')),
            lastJoinedAt: new Date()
        },
        $toggle: {
            isPremium: true
        },
    },
    $options: { $upsert: true }
});


/* Update Many Rows */
await Member.$updateMany({
    $where: {
        isPremium: true,
        badges: {
            $in: [['Verify', 'VIP']]
        }
    },
    $update: {
        $set: {
            badges: []
        },
        $toggle: {
            isPremium: true
        }
    },
});
```

## Searching in the database

Now let's search a member from the database:

<pre class="language-typescript"><code class="lang-typescript"><strong>import Member from './schemas/Member';
</strong>

/* Search All */
var allMembers = await Member.$everything();


/* Search One */
var member = await Member.$searchOne({
    $where: {
        userId: '1234567890',
    },
    $options: {
        $attributes: ['userId','username','displayName','avatar','banner'],
        $raw: true
    }
});


/* Search Many */
var memberList = await Member.$search({
    $where: {
        isPremium: true
    },
    $options: {
        $sort: {
            lastJoinedAt: -1,
            createdAt: -1
        },
        $limit: 30,
        $cache: true
    }
});


/* Search By Id */
var searchMemberById = await Member.$searchById('7ca9320b-1803-459c-a1ff-39b8d5e14a25');


/* Search By Ids */
var searchMembersByIds = await Member.$searchByIds([
    '7ca9320b-1803-459c-a1ff-39b8d5e14a25',
    '7ca9320b-1803-459c-a1ff-39b8d5e14a26',
    '7ca9320b-1803-459c-a1ff-39b8d5e14a27'
]);


/* Distinct Rows */
var memberListDistinct = await Member.$distinct({
    $field: ['userId','username','displayName'],
    $options: {
        $cache: { $key: 'memberList', $ttl: 60_000 }
    }
});


/* Get Count */
var count = await Member.$count({
    $where: {
        lastJoinedAt: {
            $gte: new Date('2021-01-01')
        }
    },
    $options: {
        $paranoid: true
    }
});


/* Search And Get Count */
var [ members, count ] = await Member.$searchAndCount({
    $where: {
        createdAt: {
            $lte: new Date('2021-01-01'),
            $gte: new Date('2020-01-01')
        }
    }
});

</code></pre>

## Deleting in the database

Now let's delete a member from the database:

```typescript
import Member from './schemas/Member';


/* Delete All */
await Member.$truncate();


/* Delete One */
var deletedMember = await Member.$delete({
    $where: {
        userId: '1234567890',
        isPremium: {
            $eq: false
        }
    }
});


/* Delete Many */
var deletedMembers = await Member.$deleteMany({
    $where: {
        isPremium: false,
        banner: {
            $startsWith: '.png'
        }
    },
    $options: {
       $limit: 40,
       $logging(sql, benchmark) {
            console.log(`${sql} took ${benchmark}ms`);
       },
       $force: true
    }
});


/* Soft Delete One */
await Member.$softDelete({
    $where: {
        username: 'fivesobes'
    }
});


/* Soft Delete Many */
await Member.$softDeleteMany({
    $where: {
        isPremium: false
    },
    $options: {
        $limit: 5
    }
});
```
