You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

lambdaorm

Package Overview
Dependencies
Maintainers
1
Versions
263
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lambdaorm

ORM

0.7.2
npmnpm
Version published
Weekly downloads
279
1228.57%
Maintainers
1
Weekly downloads
 
Created
Source

λORM

IMPORTANT: the library is in an Beta version!!!

λORM is an ORM for Node.js which bases its queries on a business model, abstracting from the physical model. By means of rules the corresponding Data Source is determined and by definition of mappings how the business model is mapped with the physical one.

What differentiates λORM from other ORMs:

  • Obtain or modify records from different Databases in the same query.
    These Databases may be from different engines (Example: MySQL, PostgreSQL, MongoDB, etc.)

  • Abstraction of the physical model, being the same to work with a single database than with multiple ones.

  • Define different stages for a business model.
    You can define a stage where you work with a MySQL instance and another stage where you work with Oracle and MongoDB.

  • Friendly query syntax, being able to write in the programming language itself as in a string.
    Expressions are parsed in the same way as with an expression language.

Features

  • Supports MySQL, MariaDB, PostgresSQL, Oracle, SqlServer, SqlJs and MongoDB.
  • TypeScript and JavaScript support
  • Schema Configuration
    • Decoupling the business model from physical model
    • Configuration in json or yml formats
    • Definition of mappings to map the business model with the physical model
    • Extends entities
    • Environment variables
    • define indices, unique keys and constraints
  • Query Language
  • Repositories and custom repositories
  • Using multiple database instances
  • Transactions and distributed transactions
  • BulkInsert
  • Connection pooling
  • Listeners and subscribers
  • High performance
  • CLI

Schema Configuration

The schema includes all the configuration that the ORM needs.

The schema separates the definition of the business model (Domain) from the persistence of the data (Infrastructure).

In the domain, the entities and enumerators that represent the business model are completely clean, without any attributes that couple them to persistence.

All queries are made according to the business model, so all queries are decoupled from the physical model of the data.

In the infrastructure, all the necessary configuration is defined to be able to persist and obtain the data from the different sources.

The schema configuration can be done in a yaml, json file or passed as a parameter when initializing the ORM.

All the expressions that are used for the definition of conditions and for the execution of actions are based on the expression engine js-expressions

More info

Schema Configuration Example:

This example poses a stage where two sources are accessed. Data source 1 is MySQL and contains the Countries table and source 2 is PostgreSQL contains the States table.

In the case of the Countries entity, both the name of the table and the fields coincide with the name of the entity and the name of the properties, so the mapping is transparent.

But in the case of the States entity, the name of the table and its fields differ, so the mapping defines the mapping.

diagram

View schema configuration

More info

Query Language

The query language is based on javascript lambda expression. These expressions can be written as javascript code by browsing the business model entities.

Expressions can also be sent as a string

λOrm translates the expression into the language corresponding to each database engine.

Query Language Example:

Countries
	.filter(p=> p.region == region)	
	.map(p=> [p.name,p.subregion,p.latitude,p.longitude])
	.include(p => p.states.filter(p=> substr(p.name,1,1)=="F")
		  .map(p=> [p.name,p.latitude,p.longitude])
	)
	.page(1,3)

where the SQL equivalent of the expression is:

SELECT c.name AS `name`, c.subregion AS `subregion`, c.latitude AS `latitude`, c.longitude AS `longitude`, c.iso3 AS `__iso3` 
FROM Countries c  
WHERE c.region = ? 
LIMIT 0,3

SELECT s.NAME AS "name", s.LATITUDE AS "latitude", s.LONGITUDE AS "longitude", s.COUNTRY_CODE AS "__parentId" 
FROM TBL_STATES s  
WHERE SUBSTR(s.NAME,1,1) = 'F'
  AND s.s.COUNTRY_CODE IN (?) 

Advantage:

  • Use of the same programming language.
  • No need to learn a new language.
  • Expressions easy to write and understand.
  • Use of the intellisense offered by the IDE to write the expressions.
  • Avoid syntax errors.

Usage

To work with the orm we can do it using the singleton object called "orm" or using repositories.

Object orm

This orm object acts as a facade and from this we access all the methods.

When the orm.init() method is called, the orm initialization will be executed from the configuration.

execute method:

This method receives the expression as a javascript lambda function or a string.

Use lambda expression:

The advantage of writing the expression as a javascript lambda function is that this way we will have the help of intellisense and we will make sure that the expression has no syntax errors.

import { orm } from 'lambdaorm'
(async () => {
	await orm.init()	
	const query = (region:string) => 
		Countries.filter(p=> p.region == region)			
			.map(p=> [p.name,p.subregion,p.latitude,p.longitude])
			.include(p => p.states.filter(p=> substr(p.name,1,1)=="F")
				.map(p=> [p.name,p.latitude,p.longitude])
			)
			.page(1,3)
	const result = await orm.execute(query, { region: 'Asia' })
	console.log(JSON.stringify(result, null, 2))
	await orm.end()
})()

Use string expression

The advantage of writing the expression in a string is that we can receive it from outside, example UI, CLI command, stored, etc.

import { orm } from 'lambdaorm'
(async () => {
	await orm.init()	
	const query = `
	Countries
		.filter(p=> p.region == region)		
		.map(p=> [p.name,p.subregion,p.latitude,p.longitude])
		.include(p => p.states.filter(p=> substr(p.name,1,1)=="F")
			.map(p=> [p.name,p.latitude,p.longitude])
		)
		.page(1,3)`																								    
	const result = await orm.execute(query, { region: 'Asia' })
	console.log(JSON.stringify(result, null, 2))
	await orm.end()
})()

Result:

[{"name": "Afghanistan",
  "subregion": "Southern Asia",
  "latitude": "33.00000000",
  "longitude": "65.00000000",
  "states":[{"name": "Farah", "latitude": "32.49532800", "longitude": "62.26266270" },
      		{"name": "Faryab", "latitude": "36.07956130","longitude": "64.90595500" }]
 },
 {"name": "United Arab Emirates",
  "subregion": "Western Asia",
  "latitude": "24.00000000",
  "longitude": "54.00000000",
  "states": [{"name": "Fujairah","latitude": "25.12880990","longitude": "56.32648490" }]
 },
 {"name": "Armenia",
  "subregion": "Western Asia",
  "latitude": "40.00000000",
  "longitude": "45.00000000",
  "states": []
 }]

Repositories

Repositories are associated with an entity and have various methods to interact with it.

import { orm } from 'lambdaorm'
import { CountryRepository } from './models/country'

(async () => {
	await orm.init()
	const countryRepository = new CountryRepository('stage1')
	const result = await countryRepository.query()
		.filter(p=> p.region == region)
		.page(1,3)
		.map(p=> [p.name,p.subregion,p.latitude,p.longitude])
		.include(p => p.states.filter(p=> substr(p.name,1,1)=="F")
							.map(p=> [p.name,p.latitude,p.longitude])
		).execute({ region: 'Asia' })	
	console.log(JSON.stringify(result, null, 2))
	await orm.end()
})()

More info

Includes:

λORM includes the include method to load related entities, both for OneToMany, manyToOne, and oneToOne relationships.

We can also apply filters or bring us some fields from related entities.

For each include, a statement is executed that fetches all the necessary records, then the objects with relationships are assembled in memory. In this way, multiple executions are avoided, considerably improving performance.

Includes can be used in selects, inserts, updates, deletes, and bulkInserts.

import { orm } from 'lambdaorm'
(async () => {
	await orm.init()
	const query = (id:number) => 
	Orders.filter(p => p.id === id)
		.include(p => [p.customer.map(p => ({ name: p.name, address: concat(p.address, ', ', p.city, ' (', p.postalCode, ')  ', p.country) })),
			p.details.include(p => p.product
				.include(p => p.category.map(p => p.name))
				.map(p => p.name))
				.map(p => [p.quantity, p.unitPrice])])
		.map(p => p.orderDate)
	const result = await orm.execute(query)
	console.log(JSON.stringify(result, null, 2))
	await orm.end()
})()

The previous sentence will bring us the following result:

[{"orderDate": "1996-07-03T22:00:00.000Z",
  "customer": { "name": "Vins et alcools Chevalier",
				  "address": "59 rue de l'Abbaye, Reims (51100)  France"
				},
  "details":[
	{"quantity": 12, "unitPrice": 14,
	  "product": { "name": "Queso Cabrales",
					"category": { "name": "Dairy Products"}}
	},
	{"quantity": 10, "unitPrice": 9.8,
	 "product": { "name": "Singaporean Hokkien Fried Mee",
				  "category": { "name": "Grains/Cereals" 	}}
	},
	{"quantity": 5, "unitPrice": 34.8,
	 "product": { "name": "Mozzarella di Giovanni",
				  "category": { "name": "Dairy Products" }}
	}]
}]

More info

Query expression metadata

λORM has the following methods to extract metadata information from expressions.

To execute these methods it is not necessary to connect to the database.

methodDescriptionPath
parametersGet parameters in the expressionorm.parameters(expression)
modelGet model of the result in an executionorm.model(expression)
metadataGet metadata of the expressionorm.metadata(expression)
sentenceGet sentence in the dialect of the physical modelorm.sentence(expression)
constraintsGet constraints of expressionorm.constraints(expression)

more info

CLI

Install the package globally to use the CLI commands to help you create and maintain projects

npm install lambdaorm-cli -g

CLI Commands

CommandDescription
versionPrints lambdaorm version this project uses.
initGenerates lambdaorm project structure.
updateupdate model, packages and project structure.
syncSynchronize database.
importImport data from file to database
exportExport data from a database
executeExecute an expression lambda or return information
dropRemoves all database objects but not the database.

CLI package

Documentation

Keywords

orm

FAQs

Package last updated on 15 Sep 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts