RDB

The ultimate ORM for Node and Typescript

README

Orange ORM Logo

The ultimate Object Relational Mapper for Node.js and Typescript, offering seamless integration with a variety of popular databases. Whether you're building applications in TypeScript or JavaScript  (including both CommonJS and ECMAScript), Orange ORM has got you covered.

Key Features


Rich Querying Model: Orange provides a powerful and intuitive querying model, making it easy to retrieve, filter, and manipulate data from your databases.
Active Record: With a concise and expressive syntax, Orange enables you to interact with your database using the Active Record Pattern .
No Code Generation Required: Enjoy full IntelliSense, even in table mappings, without the need for cumbersome code generation.
TypeScript and JavaScript Support: Orange fully supports both TypeScript and JavaScript, allowing you to leverage the benefits of static typing and modern ECMAScript features.
Works in the Browser: You can securely use Orange in the browser by utilizing the Express.js plugin, which serves to safeguard sensitive database credentials from exposure at the client level. This method mirrors a traditional REST API, augmented with advanced TypeScript tooling for enhanced functionality.

Supported Databases


✅ Postgres✅ MS SQL✅ MySQL✅ Oracle✅ SAP ASE✅ SQLite

This is the Modern Typescript Documentation. Are you looking for the Classic Documentation ?

Sponsorship ♡


If you value the hard work behind Orange and wish to see it evolve further, consider sponsoring . Your support fuels the journey of refining and expanding this tool for our developer community.

Installation


  1. ``` shell
  2. $ npm install orange-orm
  3. ```

Example


Watch the tutorial video on YouTube

Relations diagram

Here we choose SQLite.

  1. ``` shell
  2. $ npm install sqlite3
  3. ```

📄 map.ts

  1. ``` js
  2. import orange from 'orange-orm';

  3. const map = orange.map(x => ({
  4.   customer: x.table('customer').map(({ column }) => ({
  5.     id: column('id').numeric().primary().notNullExceptInsert(),
  6.     name: column('name').string(),
  7.     balance: column('balance').numeric(),
  8.     isActive: column('isActive').boolean(),
  9.   })),

  10.   order: x.table('_order').map(({ column }) => ({
  11.     id: column('id').numeric().primary().notNullExceptInsert(),
  12.     orderDate: column('orderDate').date().notNull(),
  13.     customerId: column('customerId').numeric().notNullExceptInsert(),
  14.   })),

  15.   orderLine: x.table('orderLine').map(({ column }) => ({
  16.     id: column('id').numeric().primary(),
  17.     orderId: column('orderId').numeric(),
  18.     product: column('product').string(),
  19.     amount: column('amount').numeric(),
  20.   })),

  21.   package: x.table('package').map(({ column }) => ({
  22.     id: column('packageId').numeric().primary().notNullExceptInsert(),
  23.     lineId: column('lineId').numeric().notNullExceptInsert(),
  24.     sscc: column('sscc').string() //the barcode
  25.   })),

  26.   deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
  27.     id: column('id').numeric().primary(),
  28.     orderId: column('orderId').numeric(),
  29.     name: column('name').string(),
  30.     street: column('street').string(),
  31.     postalCode: column('postalCode').string(),
  32.     postalPlace: column('postalPlace').string(),
  33.     countryCode: column('countryCode').string(),
  34.   }))

  35. })).map(x => ({
  36.   orderLine: x.orderLine.map(({ hasMany }) => ({
  37.     packages: hasMany(x.package).by('lineId')
  38.   }))
  39. })).map(x => ({
  40.   order: x.order.map(v => ({
  41.     customer: v.references(x.customer).by('customerId'),
  42.     lines: v.hasMany(x.orderLine).by('orderId'),
  43.     deliveryAddress: v.hasOne(x.deliveryAddress).by('orderId'),
  44.   }))
  45. }));

  46. export default map;
  47. ```

📄 update.ts

  1. ``` js
  2. import map from './map';
  3. const db = map.sqlite('demo.db');

  4. updateRow();

  5. async function updateRow() {
  6.   const order = await db.order.getById(2, {
  7.     lines: true
  8.   });
  9.   order.lines.push({
  10.     product: 'broomstick',
  11.     amount: 300
  12.   });

  13.   await order.saveChanges();
  14. }
  15. ```

📄 filter.ts

  1. ``` js
  2. import map from './map';
  3. const db = map.sqlite('demo.db');

  4. getRows();

  5. async function getRows() {
  6.   const orders = await db.order.getAll({
  7.     where: x => x.lines.any(line => line.product.contains('broomstick'))
  8.       .and(db.order.customer.name.startsWith('Harry')),
  9.     lines: {
  10.       packages: true
  11.     },
  12.     deliveryAddress: true,    
  13.     customer: true
  14.   });  
  15. }
  16. ```